组合寄生式继承是javascript最成熟推荐的继承模式,它用object.create设置子类原型并调用父类构造函数初始化实例属性,兼顾实例属性继承与原型方法复用,es6 class本质即为此模式。

组合寄生式继承是 JavaScript 中最成熟、推荐的继承模式,它融合了寄生式继承和借用构造函数的优点,避免了原型链继承的引用类型共享问题,也规避了盗用构造函数(经典继承)无法复用父类方法的缺陷。核心在于:用 Object.create 正确设置子类原型,同时在子类构造函数中调用父类构造函数初始化实例属性。
一、明确继承目标与关键约束
标准组合寄生式继承需满足以下四点:
- 子类实例能访问父类实例属性(通过
Parent.call(this)) - 子类原型链正确指向父类原型(即
Child.prototype.__proto__ === Parent.prototype) - 子类能复用父类原型上的方法(不重复创建,不污染父类原型)
- 支持
instanceof和isPrototypeOf的正确判断
二、标准核心模板代码(ES5 兼容写法)
以下为符合《ECMAScript 5.1》及主流规范(如 Airbnb、StandardJS)的最小可靠实现:
function Parent(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
Parent.prototype.sayName = function() {
return this.name;
};
function Child(name, age) {
// 1. 借用构造函数:继承实例属性
Parent.call(this, name);
this.age = age;
}
// 2. 创建父类原型副本,赋给子类原型(关键!)
Child.prototype = Object.create(Parent.prototype);
// 3. 修正 constructor 指向(否则 Child.prototype.constructor === Parent)
Child.prototype.constructor = Child;
// 4. 添加子类特有方法(可选)
Child.prototype.sayAge = function() {
return this.age;
};
三、为什么必须用 Object.create(Parent.prototype)?
直接写 Child.prototype = Parent.prototype 会导致子类修改原型时意外影响父类;而 new Parent() 会执行父类构造函数,可能产生副作用(如初始化非预期状态或副作用逻辑)。Object.create 安全、轻量、语义清晰——它只建立原型链连接,不触发构造函数。
常见错误写法对比:
- ❌
Child.prototype = new Parent();—— 执行父构造函数,且colors成为所有子类实例共享 - ❌
Child.prototype = Parent.prototype;—— 子类原型与父类原型完全同一对象,破坏封装 - ✅
Child.prototype = Object.create(Parent.prototype);—— 纯原型链委托,零副作用
四、ES6+ 建议:优先使用 class 语法(本质仍是该模式)
现代项目应直接使用 class,其底层编译/运行时行为就是标准化的组合寄生式继承:
class Parent {
constructor(name) {
this.name = name;
this.colors = ['red', 'blue'];
}
sayName() {
return this.name;
}
}
class Child extends Parent {
constructor(name, age) {
super(name); // 等价于 Parent.call(this, name)
this.age = age;
}
sayAge() {
return this.age;
}
}
注意:extends 会自动完成 Object.create(Parent.prototype) 和 constructor 修复,无需手动处理,更安全简洁。











