构造函数
构造函数的问题:其定义的方法会在每个实例上都创建一遍,这样的话的,就不具有复用行,明明业务逻辑都是一样的;
原型
原型链的问题(仅仅通过new的方式)
- 主要问题出现在原型中包含引用值的时候。在一个实例上操作原型上的引用值,会导致所有实例都变化。
- 第二个问题在于:子类型实例化时,不能给父类型的构造函数传参
盗用构造函数(通过使用 call()(或 apply())方法)
function SuperType() {
this.colors = ["red", "blue", "green"];
}
function SubType() {
SuperType.call(this);
}
let instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
let instance2 = new SubType();
console.log(instance2.colors); // "red,blue,green"
相比于原型链的优点有二:
- 在SuperType.call(this)的时候,运行了SuperType()中所有的初始化代码,结果就是每个实例都有自己的colors属性;
- 因为使用了call或apply,因此可以通过子类构造函数向父类构造函数中传值(如下):
function SuperType(name){ this.name = name;
}
function SubType() {
// 继承 SuperType 并传参 SuperType.call(this, "Nicholas");
// 实例属性
this.age = 29;
}
let instance = new SubType();
console.log(instance.name); // "Nicholas";
console.log(instance.age); // 29
盗用构造函数的问题
- 仅仅能使用父类原型上的数据,无法使用原型上的方法,因此如果要想自己有方法用,必须自己给自己定义,其他的都用不了,因此不能单独使用
组合式继承(综合了原型链和盗用构造函数)
基本的思路就是使用原型链继承原型上的方法,而通过盗用构造函数继承实例属性。这样即把方法定义在原型上以实现复用,又让每个实例都有自己的属性。
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() { console.log(this.name);
};
function SubType(name, age){ // 继承属性
SuperType.call(this, name);
this.age = age;
}
// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() { console.log(this.age);
};
let instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
instance1.sayName(); // "Nicholas";
instance1.sayAge(); // 29
let instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // "red,blue,green"
instance2.sayName(); // "Greg";
instance2.sayAge(); // 27