原型链继承通过子类原型指向父类实例实现方法共享,而非复制;需修正constructor指向并避免引用类型属性共享。

原型链本身不“借用”方法,而是让子类实例顺着 __proto__ 链向上查找,自然访问到父类原型上的方法。所谓“方法借用”,其实是误解;真正发生的是**方法共享与动态绑定**——子类实例调用时,this 指向自身,但函数体从父类原型上取来执行。
原型链继承的核心机制
子类的 prototype 被设为父类的一个实例,于是子类原型对象内部的 [[Prototype]] 指向父类原型。这样,所有子类实例都能通过隐式原型链访问父类原型上的方法。
- 父类方法定义在
Parent.prototype上,不是挂在实例上 - 子类实例没有复制方法,只是在查找时“路过”父类原型并执行它
- 执行时的
this是当前子类实例,所以能正确读写自己的属性(如this.name)
为什么不能直接用 Parent.prototype 赋值?
如果写 Child.prototype = Parent.prototype,子类和父类就共用同一套原型。一旦给 Child.prototype 添加方法,Parent.prototype 也会被污染——这破坏了封装性。
- 正确做法是
Child.prototype = new Parent(),创建一个干净的中间对象 - 这个中间对象继承了
Parent.prototype的全部方法,又独立于父类原型 - 后续可在
Child.prototype上安全添加子类专属方法
必须修正 constructor 指向
把 Child.prototype 设为 new Parent() 后,它的 constructor 会指向 Parent,而不是 Child。这会影响 instance.constructor 判断和部分依赖构造器的逻辑。
- 手动修复:
Child.prototype.constructor = Child - 更严谨的做法是用
Object.defineProperty设置constructor为不可枚举,避免被for...in遍历到
注意引用类型属性的共享陷阱
如果父类构造函数中初始化了引用类型(如数组、对象),这些属性会落在 new Parent() 创建的原型对象上——所有子类实例共享同一份。
- 例如
this.colors = ['red']写在Parent构造函数里 → 所有Child实例共用这个数组 - 修改
child1.colors.push('blue'),child2.colors也会变 - 解决办法:把引用类型属性移到构造函数内,配合
call继承(即组合继承),或改用 ES6 class











