一、借助构造函数实现继承
子类构造函数中通过call执行父类构造函数并绑定this,可以实现私有属性的继承并且实例对象私有属性相互独立,缺点是无法继承父类的原型方法;
function Parent1 () {
this.name = 'parent1';
}
Parent1.prototype.say = function () {
};
function Child1 () {
Parent1.call(this);
this.type = 'child1';
}
console.log(new Child1(), new Child1().say());
二、借助原型链实现继承
子类原型对象指向父类实例,父类私有属性与原型方法都可以继承,缺点一是修改原型对象引用类型数据的值会影响其他实例对象,改变一个值会影响另一个(除非直接赋值改变引用,会创建新的副本);缺点二是无法通过instanceof判断实例对象是子类还是父类创建的(construtor都指向了父类)。
function Parent2 () {
this.name = 'parent2';
this.play = [1, 2, 3];
}
function Child2 () {
this.type = 'child2';
}
Child2.prototype = new Parent2();
var s1 = new Child2();
var s2 = new Child2();
console.log(s1.play, s2.play);
s1.play.push(4);
三、构造函数+原型链组合方式
结合两种方式的优势
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3 () {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);
组合继承优化
- 减少构造函数执行次数
Child3.prototype = Parent3.prototype;
- 减少构造函数执行次数,同时指明子类实例的构造器(最优方案)
Child3.prototype = Object.create(Parent3.prototype)(创建副本)
Child3.prototype.constructor = Child3 // 重新绑定construtor