javascript原型链继承通过委托实现,子类原型指向父类原型(object.create(animal.prototype)),属性方法沿[[prototype]]链向上查找,不复制只链接,并需修复constructor指向。

JavaScript 中用原型链实现基于委托的继承,核心是让子类型的实例能访问父类型的属性和方法,不复制,而是通过 __proto__ 链向上查找——这就是“委托”:找不到就问上级,一级一级往上问,直到 Object.prototype 或 null。
让子构造函数的 prototype 指向父构造函数的实例
这是最直接体现“委托”的方式。子类原型不是空对象,而是父类的一个实例,因此天然继承其所有实例属性和方法(包括那些定义在父类 prototype 上的)。
示例:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a sound');
};
<p>function Dog(name, breed) {
Animal.call(this, name); // 借用构造函数,继承实例属性
this.breed = breed;
}</p><p>// 关键一步:Dog.prototype = new Animal();<br>
// 这样 Dog 的实例就能委托到 Animal 实例上,再委托到 Animal.prototype
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // 修复 constructor 指向</p><p>Dog.prototype.bark = function() {
console.log(this.name + ' barks!');
};</p>此时执行:
const myDog = new Dog('Leo', 'Golden Retriever');
myDog.bark(); // Leo barks!
myDog.speak(); // Leo makes a sound ← 委托自 Animal.prototype
console.log(myDog instanceof Dog); // true
console.log(myDog instanceof Animal); // true ← 因为 Dog.prototype 是 Animal 的实例
为什么用 Object.create 而不是 new Animal()?
直接写 Dog.prototype = new Animal() 看似简单,但有隐患:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 如果
Animal构造函数中有副作用(如发请求、改全局状态),每次设置原型都会触发; - 若
Animal需要参数(比如必须传name),new Animal()就会报错或传入无效值(如new Animal(undefined)); -
Object.create(Animal.prototype)只建立原型链接,不调用构造函数,安全干净。
委托的本质:属性查找遵循 [[Prototype]] 链
当你访问 myDog.speak 时,JS 引擎按如下顺序查找:
- 查
myDog自身是否有speak→ 没有; - 查
myDog.__proto__(即Dog.prototype)→ 没有; - 查
Dog.prototype.__proto__(即Animal.prototype)→ 有,返回该方法; - 执行时,
this仍是myDog,所以this.name正确取到实例属性。
这个过程就是委托:不拥有,但可使用;不复制,只链接。
注意 constructor 属性的修复
用 Object.create 替换原型后,Dog.prototype.constructor 会变成 Animal,影响类型识别和某些依赖 constructor 的逻辑(比如序列化、反射)。所以要手动修复:
Dog.prototype.constructor = Dog;
也可以在创建时一并处理:
Dog.prototype = Object.assign(Object.create(Animal.prototype), {
constructor: Dog,
bark() { /* ... */ }
});
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










