寄生组合式继承是目前最高效、最符合es5+实践的原型链继承方案,它通过空函数桥接避免父类构造函数被多次调用,完整保留原型链关系和instanceof正确性,并支持可复用工具函数与es6 class语法兼容。

用 寄生组合式继承 搭建原型链继承体系,是目前最高效、最符合 ES5+ 实践的方案——它避免了父类构造函数被多次调用,又完整保留原型链关系和 instanceof 正确性。
核心:只调用一次父类构造函数
传统组合继承会在子类构造函数中调用父类构造(如 Parent.call(this)),又在设置原型时用 new Parent(),导致父类初始化逻辑执行两次。寄生组合式继承通过一个空函数桥接原型,彻底规避这个问题:
function inheritPrototype(Child, Parent) {
const F = function() {};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
}
这样,Child.prototype 直接关联到 Parent.prototype,不触发 Parent 构造逻辑,也不污染实例属性。
封装成可复用的继承工具函数
把继承逻辑抽离为通用函数,便于多个子类统一调用:
- 支持传入自定义子类方法对象(类似 Object.assign)
- 自动绑定 constructor,避免丢失
- 兼容 TypeScript 类型推导(若使用 JSDoc 或 .d.ts)
function extend(Child, Parent, methods = {}) {
if (typeof Parent !== 'function') throw new Error('Parent must be a constructor');
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Object.assign(Child.prototype, methods);
}
使用示例:
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() { console.log(this.name + ' makes a sound'); };
function Dog(name, breed) {
Animal.call(this, name); // 只在这里初始化实例属性
this.breed = breed;
}
extend(Dog, Animal, {
bark() { console.log(this.name + ' barks!'); }
});
配合 ES6 class 语法保持现代风格
如果项目已用 class,不必放弃原型链本质——class extends 底层就是寄生组合式继承的语法糖。只需注意:
- 子类 constructor 中必须显式调用
super(),否则无法访问this - 静态方法和 getter/setter 会自动继承(基于 [[Prototype]] 链)
- 多个子类共享同一套父类原型方法,内存开销最小
无需额外封装,直接写即可高效复用:
class Vehicle {
constructor(brand) { this.brand = brand; }
start() { console.log(`${this.brand} is starting`); }
}
class Car extends Vehicle {
constructor(brand, model) {
super(brand);
this.model = model;
}
}
避免常见陷阱
高效继承的关键在于“不冗余、不断链、不污染”:
- 不用
Child.prototype = Parent.prototype—— 会污染父类原型 - 不用
Child.prototype = new Parent()—— 触发无意义实例化 - 不忽略
constructor重置 —— 否则instance.constructor指向错误 - 不在原型上放可变引用(如数组、对象)—— 多实例共享易引发意外修改
真正高效的继承体系,不是堆砌技巧,而是让每个子类精准获取所需能力,同时保持原型链干净、可预测、可调试。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











