构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name);
};
}
let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg要创建person实例,就要使用new操作符调用Person构造函数,这样会产生如下操作:
1、在内存中创建一个新对象;
2、这个新对象内部的[[Prototype]]特性被赋值为构造函数的Prototype属性;
3、构造函数内部的this被赋值为这个新对象;
4、执行构造函数内部代码;
5、如果构造函数返回非空对象,则返回该对象;否则返回刚创建的新对象。
该例子中,person1和person2分别保存着Person的不同实例,这两个对象都有一个constructor属性指向Person:
console.log(person1.constructor == Person); // true console.log(person2.constructor == Person); // true
补充:
1、构造函数也是函数
构造函数与普通函数唯一的区别就是调用方式不同。除此之外,构造函数也是函数。并没有把某个函数转化为构造函数的语法。任何函数只要使用new运算符调用就是构造函数,不用new操作符调用就是普通函数,比如上面的Person:
// 作为构造函数
let person = new Person("Nicholas", 29, "Software Engineer");
person.sayName();// "Nicholas"
// 作为函数调用
Person("Greg", 27, "Doctor"); // 添加到 window 对象
window.sayName();// "Greg"
// 在另一个对象的作用域中调用
let o = new Object();
Person.call(o, "Kristen", 25, "Nurse");
o.sayName(); // "Kristen"2、构造函数的问题
构造函数的主要问题是其定义的方***在每个实例上都创建一遍。对前面的例子而言,person1和person2都有sayName方法,但却是不同的Function实例。因为都是做一件事,没有必要定义两个实例。想要解决这个问题,可以把函数定义转移到构造函数外部进行:
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName() {
console.log(this.name);
}
let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");
person1.sayName(); // Nicholas
person2.sayName(); // Greg这样就解决了函数重复定义的问题,但又出现了新的问题。函数全部定义在外部扰乱了全局作用域,如果对象需要多个方法,那就要在全局作用域定义多个函数,这会导致自定义函数代码无法结合在一起,该问题可以通过原型模式解决。

