如何通过原型链实现方法的“重写”(Override)?
在 JavaScript 中,通过原型链实现方法的 “重写”(Override) 的核心思路是:在子类(或子对象)的原型链上定义同名方法,覆盖父类(或父对象)的方法。以下是具体实现步骤和代码示例:
1. 原型链方法重写的原理
- 原型链查找规则:
当调用对象的方法时,JavaScript 会优先在对象自身查找该方法,若未找到则沿原型链向上查找,直到找到第一个匹配的方法或到达链末端(null
)。 - 重写本质:
在子类原型链的 更近层级 定义同名方法,覆盖父类的方法,阻断原型链的继续查找。
2. 实现方法重写的步骤
(1) 定义父类及其原型方法
function Animal(name) {this.name = name;
}// 父类原型方法
Animal.prototype.eat = function() {console.log(this.name + " is eating.");
};
(2) 定义子类并继承父类原型链
function Dog(name) {Animal.call(this, name); // 继承父类实例属性
}// 建立原型链继承关系
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复 constructor
(3) 在子类原型上重写父类方法
// 重写 eat 方法
Dog.prototype.eat = function() {console.log(this.name + " eats dog food."); // 自定义逻辑
};
(4) 可选:在子类方法中调用父类方法(类似 super
)
Dog.prototype.eat = function() {Animal.prototype.eat.call(this); // 调用父类方法console.log("Then drinks water.");
};
3. 测试重写效果
const animal = new Animal("Generic Animal");
const dog = new Dog("Buddy");animal.eat(); // "Generic Animal is eating."
dog.eat(); // "Buddy eats dog food."(重写后的方法)// 若子类方法中调用了父类方法
dog.eat();
// 输出:
// "Buddy is eating."(父类方法)
// "Then drinks water."(子类新增逻辑)
4. ES6 class
语法中的方法重写
ES6 的 class
语法通过 extends
和 super
更简洁地实现方法重写:
class Animal {constructor(name) {this.name = name;}eat() {console.log(`${this.name} is eating.`);}
}class Dog extends Animal {eat() {super.eat(); // 调用父类方法console.log(`${this.name} drinks water.`);}
}const dog = new Dog("Buddy");
dog.eat();
// 输出:
// "Buddy is eating."
// "Buddy drinks water."
关键点总结
行为 | ES5 原型链实现 | ES6 class 实现 |
---|---|---|
重写方法 | 在子类原型上定义同名方法 | 在子类中直接定义同名方法 |
调用父类方法 | Parent.prototype.method.call(this) | super.method() |
原型链关系 | 手动设置 Child.prototype = Object.create(Parent.prototype) | 自动通过 extends 建立 |
代码可读性 | 较低 | 高(语法更贴近传统面向对象语言) |
注意事项
- 避免直接修改内置对象原型:
如重写Object.prototype.toString
可能导致不可预期的行为。 - 方法重写的优先级:
对象自身属性 > 子类原型方法 > 父类原型方法。 - 性能影响:
频繁重写方法或深层原型链可能影响性能,需合理设计。
通过原型链实现方法重写是 JavaScript 继承和多态的核心机制,理解其原理有助于编写灵活且可维护的代码。