方式
寄生+构造函数(最成熟⭐)(也叫寄生组合继承)
- 结合借用构造函数传递参数和寄生模式实现继承
- 使用真正的prototype(原型对象), 原型继承方法, 构造函数构造属性
// 该过程可以被称为寄生
function inheritPrototype(subType, superType){
var prototype = Object.create(superType.prototype); // 创建subType的原型对象,并把其__proto__属性指向父类的原型对象
prototype.constructor = subType; // 把新建的原型对象中constructor 属性正确指向子类构造函数
subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
}
// 父类初始化实例属性和原型属性
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
// 借用构造函数传递增强子类实例属性(支持传参和避免篡改)
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
// 将子类原型与父类的原型链接起来
inheritPrototype(SubType, SuperType);
// 新增子类原型属性
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType("xyc", 23);
var instance2 = new SubType("lxy", 23);
instance1.colors.push("2"); // ["red", "blue", "green", "2"]
instance1.colors.push("3"); // ["red", "blue", "green", "3"]
这是最成熟的方法,也是现在库实现的方法
不成熟的方式
- 原型链继承:将父类的实例作为子类的prototype(原型对象),通过 prototype 进行继承
- 多个子类实例共用一个父类实例,导致互相污染属性
- 构造继承:通过重新调用父类的构造函数,将父类的实例属性复制给子类
- 缺点:(存储在prototype(原型对象)中的方法就不管了)
- 组合继承:就是 原型链继承 和 构造继承,一起使用
- 缺点:父类的属性同时存在于子类实例和子类原型对象中,造成冗余
- 寄生继承:浅拷贝父类实例成一个副本对象,给这个副本对象添加一些子类的属性或方法,把这个副本作为子类的实例
- 缺点:因为浅拷贝,所以多个子类实例共用相同的属性值,导致会造成互相污染