You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

原因解释

  1. target与receiver是完全独立的对象

    • target是你传入Proxy构造函数的原始对象o,是被代理的目标本体。
    • receiver就是你创建的代理实例p,也就是new Proxy(o, ...)生成的对象。两者属于不同的对象身份,因此target === recv必然返回false。
  2. 控制台显示的是属性快照,而非对象身份
    控制台打印对象时,只会展示当前可枚举的属性值,不会标注该对象是否为代理。你看到的{ a: 'xxx' }只是对象的属性序列化结果,无法区分是原对象o还是代理p。可以在陷阱中添加验证代码:

    console.log('recv is proxy instance', recv === p); // 输出true
    

    就能确认receiver确实是代理对象p。

  3. receiver参数的核心作用
    文档中提到的receiver是“代理对象或继承自代理的对象”,在当前场景下,因为直接通过代理p访问/设置属性,所以receiver就是p本身。这个参数的主要作用是处理继承或setter中的this指向:如果目标对象的属性有setter,或者访问的是继承来的属性,receiver会确保setter中的this指向正确的上下文(代理或其继承对象),而非原目标对象。

内容的提问来源于stack exchange,提问作者bmacnaughton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 01:17:22