原型链方法重写需正确设置子类prototype指向父类原型并修复constructor,重写必须在子类原型上进行,调用父类方法须用call/apply显式绑定this。

在原型链中实现方法重写,关键在于保持继承关系正确、重写位置准确,并在需要时主动调用父类逻辑——不是自动合并,而是显式控制。
确保原型链链接完整
子构造函数的 prototype 必须通过 Object.create(Parent.prototype) 指向父类原型,不能直接赋值为 new Parent()(会共享引用类型属性),也不能遗漏 constructor 修复:
-
错误写法:
Dog.prototype = new Animal();→ 导致所有 Dog 实例共享同一份colors数组 -
正确写法:
Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; - 只有这样,
dog instanceof Animal才为 true,且方法查找能沿链向上到达 Animal.prototype
重写必须发生在子类原型上
方法重写是“替换原型上的同名函数”,不是给实例加方法,否则无法体现多态性,也浪费内存:
-
有效重写:
Dog.prototype.speak = function() { console.log('Woof!'); }; -
无效做法:
const dog = new Dog(); dog.speak = function() { ... };→ 只影响当前实例,不改变后续实例行为 - 重写后调用
dog.speak()会命中 Dog.prototype.speak,跳过 Animal.prototype.speak
手动调用父类方法需用 call/apply
原型链中没有 super 关键字,若子类重写后仍需执行父类逻辑,必须显式借用父类方法并绑定 this:
-
Animal.prototype.speak.call(this);—— 在子类方法内安全调用父版本 - 不能写
Animal.speak(),因为普通函数调用时 this 会丢失,指向 undefined 或全局对象 - 如果父方法依赖
this.name等实例属性,call(this)是唯一可靠方式
区分“覆盖”与“扩展”的意图
重写本身只是替换;是否复用父逻辑,完全由你决定。常见模式有三种:
-
完全替换:只写新逻辑,不调父类 —— 适用于行为彻底不同(如
Animal.eat()vsPlant.photosynthesize()) -
前置增强:先调
Animal.prototype.method.call(this),再执行子类额外操作 —— 适合校验、日志等钩子场景 - 后置增强:先做子类逻辑,再调父类 —— 较少用,注意避免父逻辑被异常中断

















