组合继承通过构造函数继承确保子类实例属性独立,用parent.call(this)初始化引用类型属性;原型链继承复用方法但不解决属性共享;应使用object.create(parent.prototype)而非new parent()设置原型,并手动修复constructor指向。

原型继承本身无法保证子类实例的独立性——这是它的固有缺陷。真正起作用的是“组合继承”,它用构造函数继承来兜底,确保每个实例拥有自己的一份属性。
引用类型属性必须靠构造函数继承初始化
父类中定义在 this 上的引用类型(如数组、对象),如果只靠原型链继承,所有子类实例会共享同一份内存地址。解决办法是在子类构造函数里调用父类构造函数:
- 用 Parent.call(this, ...) 触发父类初始化逻辑
- 让 this.colors = ['red'] 这类赋值在每个子类实例上重新执行
- 这样每个实例的 colors 就是独立数组,互不影响
方法复用不破坏独立性,但不能替代属性隔离
把方法放在父类原型上(如 Parent.prototype.sayName),再让子类原型指向它(Child.prototype = Object.create(Parent.prototype)),确实能复用函数逻辑。但这只解决方法共享问题,对 this 上的属性毫无影响——它们仍需构造函数继承来保障独立。
避免用 new Parent() 设置子类原型
直接写 Child.prototype = new Parent() 看似简单,但会导致两个问题:
- 父类构造函数被多执行一次(可能引发副作用,比如重复发请求或初始化无效数据)
- 子类原型上混入了父类实例属性(如 colors),这些属性会被所有子类实例间接共享
- 正确做法是用 Object.create(Parent.prototype),只继承原型链,不执行构造逻辑
constructor 指向必须手动修复
改写子类原型后,Child.prototype.constructor 会指向 Parent。这会影响 instanceof 判断和调试可读性,务必补上:
- Child.prototype.constructor = Child
- 否则新建的实例 new Child() 会显示 constructor 是 Parent











