寄生组合式继承是ES6前最接近真正类继承的模拟方式,它通过Parent.call(this)继承实例属性、Object.create(Parent.prototype)继承原型方法、手动修正constructor,避免父类构造函数被调用两次,兼顾属性私有化与方法复用。

寄生组合式继承是ES6之前最接近“真正类继承”的模拟方式,它结合了构造函数继承(解决属性私有化)和原型链继承(复用方法),同时规避了组合继承中父类构造函数被调用两次的缺陷。
核心思路:只调用一次父类构造函数
组合继承的问题在于:子类构造函数里用 Parent.call(this) 继承实例属性,又用 Child.prototype = new Parent() 设置原型——后者会再次执行父类构造函数,造成冗余(比如重复初始化引用类型属性)。寄生组合式继承用 Object.create(Parent.prototype) 替代 new Parent(),跳过执行父类构造逻辑,只复用其原型对象。
关键三步操作
-
步骤一:继承实例属性
在子构造函数中调用
Parent.call(this, ...args),把父类的实例属性(如this.name、this.colors)复制到子实例上,保证每个子实例拥有独立副本。 -
步骤二:继承原型方法
执行
Child.prototype = Object.create(Parent.prototype),让子类原型干净地指向父类原型对象,不触发父类构造函数,也不污染父类原型。 -
步骤三:修复 constructor 指向
因为
Object.create()创建的对象其constructor默认指向Parent,需手动重置:Child.prototype.constructor = Child。
一个完整示例
假设父类 Animal 有实例属性 name 和原型方法 eat:
function Animal(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
Animal.prototype.eat = function(food) {
console.log(this.name + ' eats ' + food);
};
function Dog(name, breed) {
Animal.call(this, name); // ✅ 只这里调用一次 Animal 构造函数
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype); // ✅ 不执行 Animal()
Dog.prototype.constructor = Dog; // ✅ 修正 constructor
Dog.prototype.bark = function() {
console.log('Woof!');
};
const dog1 = new Dog('Max', 'Golden');
console.log(dog1.name); // Max
console.log(dog1.breed); // Golden
dog1.eat('meat'); // Max eats meat
dog1.bark(); // Woof!
为什么比组合继承更优?
对比组合继承,寄生组合式继承避免了两个常见问题:
- 父类构造函数不会被重复执行,比如
this.colors = ['red', 'blue']不会在设置原型时再初始化一遍; - 子类原型与父类原型完全解耦,修改
Dog.prototype不会影响Animal.prototype; - 子实例既是
Dog实例,也是Animal实例(dog1 instanceof Animal === true),继承关系语义完整。


















