JavaScript中原型方法覆盖遵循就近原则和属性屏蔽机制:子类原型上定义同名方法会遮蔽父类原型方法,需确保继承关系正确建立且不切断原型链,推荐使用class语法配合super调用父类逻辑。

JavaScript 中原型对象覆盖父级方法,核心在于“就近原则”和“属性屏蔽机制”——子类原型上定义同名方法,会自动遮蔽(shadow)父类原型上的同名方法,前提是定义方式正确。
直接在子类 prototype 上赋值重写
这是最常用、最直观的方式。只要子类原型对象上存在与父类原型同名的方法,实例调用时就会优先使用子类的版本。
- 确保继承关系已建立(如
Child.prototype = Object.create(Parent.prototype)或Child.prototype = new Parent()) - 在继承之后、创建实例之前,给
Child.prototype赋值同名方法 - 注意:不能用对象字面量整体替换
Child.prototype,否则会丢失constructor指向和继承链
示例:
function Parent() {}Parent.prototype.say = function() { console.log("parent"); };
function Child() {}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 修复 constructor
// ✅ 正确覆盖
Child.prototype.say = function() { console.log("child"); };
const c = new Child();
c.say(); // 输出 "child"
重写 getter/setter 属性要特别处理
如果父类原型上用 Object.defineProperty 定义了 accessor(get/set),直接赋值 Child.prototype.prop = value 不会覆盖它,反而会触发父类 setter 或创建一个同名数据属性但不起效。
立即学习“Java免费学习笔记(深入)”;
- ❌ 错误:
Child.prototype.abc = "new"—— 无效,可能意外调用父类 setter - ✅ 正确一:用
Object.defineProperty在子类原型上重新定义 - ✅ 正确二:使用 class 语法,在子类中声明同名 get/set 访问器(推荐)
示例(class 写法):
class Parent {get value() { return "parent"; }
}
class Child extends Parent {
get value() { return "child"; } // 显式覆盖
set value(v) { console.log("child set:", v); }
}
避免切断原型链的常见错误
覆盖方法时,若错误地重置整个 prototype,会导致继承链断裂,子类实例无法访问父类方法(包括未被覆盖的那些)。
- ❌ 危险写法:
Child.prototype = { say() { ... } };—— 这会丢掉__proto__指向Parent.prototype - ✅ 安全做法:始终基于已有原型扩展,或用
Object.create(Parent.prototype)初始化 - 补充:若需批量添加多个方法,可用
Object.assign(Child.prototype, { method1(){}, method2(){} })
需要调用父类方法时用 super(仅限 class 语法)
重写不是抛弃,有时需在子类方法中保留父类逻辑并追加行为。ES6 class 提供 super 关键字安全调用父类同名方法。
- 仅在 class 的方法体内可用
super.methodName() - 构造函数中必须先调用
super(),再访问this - 函数式继承(非 class)需手动保存父类引用,如
Parent.prototype.say.call(this)
示例:
class Animal {eat() { console.log("eating..."); }
}
class Dog extends Animal {
eat() {
super.eat(); // 先执行父类逻辑
console.log("chewing dog food");
}
}


















