函数与构造函数

创建一个对象的方式中有一个构造函数模式。ECMAScript中的构造函数是用于创建特定类型对象的。如Object和Array这样的原生构造函数,运行时可以直接在执行环境中使用。

还可以自定义构造函数,以函数的形式为自己的对象类型定义属性和方法

如一个构造函数:

function Student(name,age){
    this.name = name
    this.age = age

    this.show = function(){
        console.log(`姓名:${this.name},年龄:${this.age}`);
    }
}

let s1 = new Student("XLX",25)
s1.show()    // 姓名:XLX,年龄:25

注意:

  • 构造函数名称首字母大写
  • 非构造函数小写字母开头

这里的new关键字做了哪些事:

  • new创建了一个空对象;
  • 自动设置当前新创建的空对象继承构造函数的原型对象(新对象的__proto__设为构造函数的prototype属性)
  • 调用构造函数,并将构造函数中的this统一指向正在创建的这个新对象。(让实参值强行添加到新对象中的对应的属性上);
  • 返回新对象的地址保存到变量中

其实,构造函数也是函数,构造函数与普通函数的唯一区别在于调用方式不同

  • 任何函数只要使用new操作符调用就是构造函数,不使用new操作符调用的函数就是普通函数。如上方的Student构造函数:
    • function Student(name,age){
          this.name = name
          this.age = age
      
          this.show = function(){
              console.log(`姓名:${this.name},年龄:${this.age}`);
          }
      }
      
      Student("张三",28)
      window.show()
    • 说明:
      • 这里直接通过普通函数的方式调用
      • 由于在上下文中没有使用严格模式,所以构造函数中的this指向了window(严格模式下this会指向undefined)
      • 所以这里通过普通函数的方式调用相当于window.Student("张三",28)

构造函数的问题:

主要问题在于:构造函数内的方法会在每个实例上都创建一遍。如上面的Student对象:

function Student(name,age){
    this.name = name
    this.age = age

    this.show = function(){
        console.log(`姓名:${this.name},年龄:${this.age}`);
    }
}

let s1 = new Student("张三",24)
let s2 = new Student("李四",26)
console.log(s1.show === s2.show)    // false

每个Student实例都会有一个自己的show方法实例,以这种方式创建函数会带来不同的作用域链和标识符解析。但创建新Function实例的机制是一样的,因此不同实例上的函数虽然同名却不相等

由于做的事情一样,因此没必要定义两个不同的Function实例:

 1 function Student(name,age){
 2     this.name = name
 3     this.age = age
 4     this.show = show
 5 }
 6 
 7 function show(){
 8     console.log(`姓名:${this.name},年龄:${this.age}`);
 9 }
10 
11 let s1 = new Student("张三",24)
12 let s2 = new Student("李四",26)
13 console.log(s1.show === s2.show)    // true

说明:

  • 这里的show方法相当于全局的函数。因此也是相等的

问题:

  • 这里的show方法保存在全局,容易造成全局污染
  • 解决:原型模式创建对象
原文地址:https://www.cnblogs.com/codexlx/p/14282682.html