JavaScript Proxy中target与receiver为何不相等?
JavaScript Proxy中get/set陷阱里target与receiver不相等的原因
问题描述
在使用JavaScript Proxy时,无法理解为什么get()和set()陷阱中的target与receiver不相等——从控制台日志来看它们的外观完全一致。Mozilla文档指出receiver是代理对象或继承自代理的对象,但在这个案例中控制台显示的似乎不是代理对象。(补充说明:经测试,get()和set()陷阱中的this本身就是代理对象。)
测试代码
const s = 'this is a string'; const o = {a: s}; const p = new Proxy(o, { get(target, prop, recv) { console.log('get: target', target, 'recv', recv, 'same', target === recv); return target[prop]; }, set(target, prop, value, recv) { console.log('set: target', target, 'recv', recv); Reflect.set(target, prop, value, recv); //target[prop] = value; console.log('set: target', target, 'recv', recv, 'same', target === recv); return value; }, }); let z = p.a; p.a = 'also a string'; z = p.a;
运行输出
get: target { a: 'this is a string' } recv { a: 'this is a string' } same false set: target { a: 'this is a string' } recv { a: 'this is a string' } set: target { a: 'also a string' } recv { a: 'also a string' } same false get: target { a: 'also a string' } recv { a: 'also a string' } same false
原因解释
target与receiver是完全独立的对象
target是你传入Proxy构造函数的原始对象o,是被代理的目标本体。receiver就是你创建的代理实例p,也就是new Proxy(o, ...)生成的对象。两者属于不同的对象身份,因此target === recv必然返回false。
控制台显示的是属性快照,而非对象身份
控制台打印对象时,只会展示当前可枚举的属性值,不会标注该对象是否为代理。你看到的{ a: 'xxx' }只是对象的属性序列化结果,无法区分是原对象o还是代理p。可以在陷阱中添加验证代码:console.log('recv is proxy instance', recv === p); // 输出true就能确认receiver确实是代理对象
p。receiver参数的核心作用
文档中提到的receiver是“代理对象或继承自代理的对象”,在当前场景下,因为直接通过代理p访问/设置属性,所以receiver就是p本身。这个参数的主要作用是处理继承或setter中的this指向:如果目标对象的属性有setter,或者访问的是继承来的属性,receiver会确保setter中的this指向正确的上下文(代理或其继承对象),而非原目标对象。
内容的提问来源于stack exchange,提问作者bmacnaughton
相关产品推荐
相关产品推荐

