推荐答案
// www.javascriptcn.com code example
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype); // 创建对象
prototype.constructor = subType; // 增强对象
subType.prototype = prototype; // 指定对象
}
function SuperType(name) {
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;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
console.log(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // ["red", "blue", "green", "black"]
instance1.sayName(); // "Nicholas"
instance1.sayAge(); // 29
var instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // ["red", "blue", "green"]
instance2.sayName(); // "Greg"
instance2.sayAge(); // 27本题详细解读
寄生组合式继承的原理
寄生组合式继承是 JavaScript 中实现继承的一种高效方式。它结合了原型链继承和构造函数继承的优点,同时避免了它们的缺点。
原型链继承:通过将子类的原型指向父类的实例来实现继承。缺点是父类的实例属性会被所有子类实例共享,容易造成引用类型的属性被修改。
构造函数继承:通过在子类构造函数中调用父类构造函数来实现继承。缺点是父类原型上的方法无法被继承。
寄生组合式继承的核心思想是:
- 使用构造函数继承来继承父类的实例属性。
- 使用原型链继承来继承父类的原型方法,但不会直接继承父类的实例。
实现步骤
创建父类原型的一个副本:通过
Object.create(superType.prototype)创建一个新的对象,该对象的原型指向父类的原型。这样可以避免直接修改父类的原型。增强对象:将新创建的对象的
constructor属性指向子类构造函数,以确保子类的实例能够正确识别其构造函数。指定对象:将子类的原型指向新创建的对象,这样子类就可以继承父类的原型方法。
代码解析
inheritPrototype(subType, superType)函数实现了寄生组合式继承的核心逻辑。SuperType是父类构造函数,定义了实例属性和原型方法。SubType是子类构造函数,通过SuperType.call(this, name)调用父类构造函数来继承实例属性。inheritPrototype(SubType, SuperType)调用后,SubType的原型指向了SuperType原型的副本,从而继承了父类的原型方法。SubType.prototype.sayAge是子类新增的原型方法。
优点
- 避免了多次调用父类构造函数,减少了性能开销。
- 避免了父类实例属性被所有子类实例共享的问题。
- 子类可以继承父类的原型方法,同时可以添加自己的原型方法。
总结
寄生组合式继承是 JavaScript 中最理想的继承方式,它结合了构造函数继承和原型链继承的优点,避免了它们的缺点,是一种高效且灵活的继承实现方式。