receiver的核心作用是确保getter/setter中this指向最初发起访问的对象,而非target;它必须传给Reflect以正确绑定this,否则继承链中访问器属性会因this错位而读取错误私有字段。

原型链与 Proxy 结合时,receiver 参数的核心作用是确保 getter/setter 中的 this 指向正确的调用者对象,而不是原始目标对象。若忽略 receiver 或未正确传递,继承链中访问器属性(如 get name())会丢失上下文,导致 this._name 读取错误对象的私有字段。
receiver 是谁?它为什么必须传给 Reflect
receiver 是 Proxy 陷阱(如 get、set)的第三个参数,代表最初发起属性访问的对象。比如:
– 当 admin.name 被读取,admin 就是 receiver;
– 即使 admin.__proto__ 是一个 Proxy,receiver 仍是 admin,不是 Proxy 本身,也不是 target。
Reflect.get/set 必须显式传入 receiver,因为:
- Reflect.get(target, key, receiver) 会在执行 getter 时,把 receiver 作为 this 绑定进去
- 不传 receiver 等价于传 undefined,此时 getter 内部的
this会退化为 target(即原始对象),破坏继承语义 - 这是 Reflect 设计的约定,也是 Proxy 与原型链协同工作的唯一可靠方式
不传 receiver 的典型错误场景
假设有一个用户基类和管理员子类:
立即学习“Java免费学习笔记(深入)”;
将后端 Java 接口文档转换为前端 TypeScript 类型定义(interface / type)。输入:飞书文档、Spring Boot 接口文档、Swagger/OpenAPI、手写 API 文档等。输出:包含请求参数与响应结果的 .md 文件,含完整 JSDoc 注释。触发关键词:Java 转 TS、接口转换、生成前端类型、接口文档转 TypeScript、DTO/VO/BO 转 interface、后端文档转前端类型、生成接口类型、类型定义生成。
❌ 错误写法(丢失 this):
const user = {
_name: 'Guest',
get name() { return this._name; }
};
const userProxy = new Proxy(user, {
get(target, prop) {
return target[prop]; // ❌ 没传 receiver,也没用 Reflect
}
});
const admin = { __proto__: userProxy, _name: 'Admin' };
console.log(admin.name); // → 'Guest'(错误!this 指向 user)
原因:访问 admin.name 触发 Proxy 的 get,但 target[prop] 直接取到 getter 函数并立即执行,此时函数内 this 是 user,而非 admin。
正确传递 receiver 的标准模式
所有涉及访问器或需要保持 this 的操作,都应使用 Reflect 并透传 receiver:
-
get(target, prop, receiver)→return Reflect.get(target, prop, receiver) -
set(target, prop, value, receiver)→return Reflect.set(target, prop, value, receiver) - 即使 target 是普通数据属性,也建议统一用 Reflect,保证行为一致性
✅ 正确示例:
const userProxy = new Proxy(user, {
get(target, prop, receiver) {
console.log('receiver === admin?', receiver === admin); // true
return Reflect.get(target, prop, receiver); // ✅ this 在 getter 中指向 admin
}
});
const admin = { __proto__: userProxy, _name: 'Admin' };
console.log(admin.name); // → 'Admin'
receiver 在多层代理或嵌套原型中的表现
receiver 始终是链路起点,不会被中间 Proxy 改写:
- 如果
superAdmin.__proto__ = admin,而admin.__proto__ = userProxy,那么superAdmin.name的 receiver 仍是superAdmin - 只要每个 Proxy 的
get都用Reflect.get(target, prop, receiver),this 就能逐层穿透到最外层调用者 - receiver 不是“当前代理”,也不是“当前 target”,它是调用链的根对象,由 JavaScript 引擎自动注入

















