推荐答案
在 JavaScript 中,组合继承是一种结合了原型链继承和构造函数继承的方式。它通过调用父类的构造函数来继承父类的属性,并通过将子类的原型设置为父类的实例来继承父类的方法。这种方式既能够继承父类的属性,又能够继承父类的方法,避免了原型链继承和构造函数继承各自的缺点。
// www.javascriptcn.com code example
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name, age) {
// 继承属性
Parent.call(this, name);
this.age = age;
}
// 继承方法
Child.prototype = new Parent();
Child.prototype.constructor = Child;
Child.prototype.sayAge = function() {
console.log(this.age);
};
const child1 = new Child('Alice', 10);
child1.colors.push('black');
console.log(child1.colors); // ['red', 'blue', 'green', 'black']
child1.sayName(); // Alice
child1.sayAge(); // 10
const child2 = new Child('Bob', 12);
console.log(child2.colors); // ['red', 'blue', 'green']
child2.sayName(); // Bob
child2.sayAge(); // 12本题详细解读
1. 组合继承的原理
组合继承的核心思想是通过以下两个步骤来实现继承:
继承属性:在子类的构造函数中调用父类的构造函数(
Parent.call(this, name)),这样每个子类实例都会拥有父类的属性,并且这些属性是独立的,不会相互影响。继承方法:将子类的原型对象设置为父类的一个实例(
Child.prototype = new Parent()),这样子类实例就可以通过原型链访问父类的方法。
2. 组合继承的优点
- 属性独立:每个子类实例都拥有自己的属性副本,不会相互影响。
- 方法共享:子类实例共享父类的方法,节省内存。
3. 组合继承的缺点
- 调用两次父类构造函数:一次是在创建子类原型时(
Child.prototype = new Parent()),另一次是在子类构造函数中调用父类构造函数(Parent.call(this, name))。这会导致子类原型上存在不必要的父类属性。
4. 组合继承的应用场景
组合继承适用于需要同时继承属性和方法的场景,尤其是在需要确保每个实例拥有独立的属性,同时又能共享方法的情况下。
5. 组合继承的改进
为了避免组合继承中调用两次父类构造函数的问题,可以使用寄生组合继承,这是目前 JavaScript 中最理想的继承方式。
// www.javascriptcn.com code example
function inheritPrototype(child, parent) {
const prototype = Object.create(parent.prototype);
prototype.constructor = child;
child.prototype = prototype;
}
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Parent.prototype.sayName = function() {
console.log(this.name);
};
function Child(name, age) {
Parent.call(this, name);
this.age = age;
}
inheritPrototype(Child, Parent);
Child.prototype.sayAge = function() {
console.log(this.age);
};
const child1 = new Child('Alice', 10);
child1.colors.push('black');
console.log(child1.colors); // ['red', 'blue', 'green', 'black']
child1.sayName(); // Alice
child1.sayAge(); // 10
const child2 = new Child('Bob', 12);
console.log(child2.colors); // ['red', 'blue', 'green']
child2.sayName(); // Bob
child2.sayAge(); // 12通过寄生组合继承,可以避免组合继承中调用两次父类构造函数的问题,同时保留组合继承的优点。