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>此时执行:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
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 的实例
</font><H3>为什么用 Object.create 而不是 new Animal()?</H3><p>直接写 <code>Dog.prototype = new Animal()</code> 看似简单,但有隐患:</p><ul><li>如果 <code>Animal</code> 构造函数中有副作用(如发请求、改全局状态),每次设置原型都会触发;</li><li>若 <code>Animal</code> 需要参数(比如必须传 <code>name</code>),<code>new Animal()</code> 就会报错或传入无效值(如 <code>new Animal(undefined)</code>);</li><li><code>Object.create(Animal.prototype)</code> 只建立原型链接,不调用构造函数,安全干净。</li></ul><H3>委托的本质:属性查找遵循 [[Prototype]] 链</H3><p>当你访问 <code>myDog.speak</code> 时,JS 引擎按如下顺序查找:</p><ol><li>查 <code>myDog</code> 自身是否有 <code>speak</code> → 没有;</li><li>查 <code>myDog.__proto__</code>(即 <code>Dog.prototype</code>)→ 没有;</li><li>查 <code>Dog.prototype.__proto__</code>(即 <code>Animal.prototype</code>)→ 有,返回该方法;</li><li>执行时,<code>this</code> 仍是 <code>myDog</code>,所以 <code>this.name</code> 正确取到实例属性。</li></ol><p>这个过程就是委托:不拥有,但可使用;不复制,只链接。</p><H3>注意 constructor 属性的修复</H3><p>用 <code>Object.create</code> 替换原型后,<code>Dog.prototype.constructor</code> 会变成 <code>Animal</code>,影响类型识别和某些依赖 constructor 的逻辑(比如序列化、反射)。所以要手动修复:</p><font face="monospace"><pre class="brush:php;toolbar:false;">
Dog.prototype.constructor = Dog;
也可以在创建时一并处理:
Dog.prototype = Object.assign(Object.create(Animal.prototype), {
constructor: Dog,
bark() { /* ... */ }
});

















