JavaScript原型链委托的核心是属性查找失败时自动沿__proto__向上委托,this始终指向调用者对象;常用方式有构造函数+prototype、Object.create()和__proto__(不推荐);class和Object.setPrototypeOf()为现代替代方案。

JavaScript 中用原型链实现对象间委托调用,核心是让一个对象的 __proto__(或通过 Object.setPrototypeOf()、构造函数 prototype)指向另一个对象,从而在属性/方法查找失败时,自动沿原型链向上委托到父级对象。
理解委托的本质:属性查找失败时的自动跳转
委托不是主动调用,而是 JavaScript 引擎在访问对象属性时的隐式行为:当前对象找不到该属性 → 查找其 [[Prototype]](即 __proto__)指向的对象 → 找不到再继续向上,直到 null。只要链路存在,就能“借用”上游的方法或数据。
- 委托生效的前提是:属性未在本地定义,且原型链上存在同名可访问属性
- 方法内部的
this始终指向**调用时的原始对象**,不是原型上的那个对象(这点很重要) - 修改委托对象的属性,不会影响原型对象;但若属性是引用类型(如数组、对象),修改其内部值会影响所有共享该引用的地方
三种常用设置原型链的方式
目标:让 child 能委托调用 parent 的方法。
-
方式一:构造函数 + prototype(最经典)
把共享方法放在构造函数的prototype上,实例自然继承:
function Parent() {}<br>Parent.prototype.say = function() { console.log('Hello'); };<br>function Child() {}<br>Child.prototype = Object.create(Parent.prototype);<br>Child.prototype.constructor = Child;<br>const c = new Child();<br>c.say(); // Hello(委托成功) -
方式二:Object.create() 直接创建委托关系
适合纯对象间委托,不涉及构造函数:
const parent = { greet() { return `Hi, I'm ${this.name}`; } };<br>const child = Object.create(parent);<br>child.name = 'Alice';<br>child.greet(); // "Hi, I'm Alice" -
方式三:动态设置 __proto__(不推荐用于生产)
__proto__是非标准但广泛支持的访问器,仅作学习理解用:
const parent = { log() { console.log('from parent'); } };<br>const child = {};<br>child.__proto__ = parent;<br>child.log(); // from parent
注意 this 指向与数据隔离
委托调用时,方法内的 this 是调用者本身,不是原型对象。这意味着方法可以自然访问调用者的自有属性:
立即学习“Java免费学习笔记(深入)”;
- 上面
greet()示例中,this.name取的是child.name,不是parent.name - 如果想让委托方法操作原型上的数据,需显式访问(如
this.constructor.prototype.xxx),但通常不这么做 - 避免在原型上放可变对象(如
prototype.items = []),否则所有实例共享同一数组——应把初始化逻辑放进构造函数体内
现代替代方案:class 语法糖与 Object.setPrototypeOf()
class 本质仍是基于原型链,只是更简洁:
-
class Child extends Parent { }自动建立Child.prototype→Parent.prototype的委托链 - 运行时动态修改委托,可用
Object.setPrototypeOf(obj, newProto),比直接改__proto__更规范 - 检查委托关系用
Object.getPrototypeOf(obj) === target或obj instanceof Constructor


















