
寄生组合式继承的实现逻辑可以拆解为两个明确、互不干扰的阶段:实例属性初始化和原型链构建。这两个阶段分别解决“每个实例该拥有什么”和“所有实例该共享什么”,是它优于组合继承的关键所在。
第一阶段:在子类构造函数中用 call 初始化实例属性
这个动作发生在每次 new SubType() 时,目标是让每个实例拥有自己独占的数据空间。
- 在子类构造函数内部调用 SuperType.call(this, ...args),把父类构造逻辑“借”过来执行一次
- this.name、this.colors = ['red'] 这类引用类型属性,因此各自独立,不会被多个实例意外共享
- 父类构造函数中的副作用(如发请求、改全局变量)也只触发一次,避免冗余执行
第二阶段:用 Object.create 构建干净的原型链
这个动作发生在类定义阶段(即代码执行到 SubType.prototype = ... 时),目标是复用方法,但绝不重复运行父类构造逻辑。
- 不写 SubType.prototype = new SuperType()——那会再次执行父构造函数,并在原型上留下无意义的 name/colors
- 改用 Object.create(SuperType.prototype),创建一个空对象,其 [[Prototype]] 直接指向父类原型
- 手动设置 SubType.prototype.constructor = SubType,确保 new 出来的实例能正确识别自身构造器
两个阶段协同带来的实际效果
只有当这两步都到位,才能达成寄生组合式继承的设计初衷:
- 子类实例之间完全隔离:比如修改 instance1.colors 不会影响 instance2.colors
- 所有实例共享同一份方法:sayName、render 等从 SuperType.prototype 沿原型链获取,节省内存
- 原型链完整可追溯:instance.__proto__ → SubType.prototype → SuperType.prototype → Object.prototype
- 父类构造函数全程仅执行一次,没有隐式开销











