Reflect 是 Proxy 的默认行为实现层,必须配合使用:set/get 拦截中需用 Reflect.set/get 以保持属性描述符、this 绑定、原型链查找等语义正确性。

Reflect 是 JavaScript 中一个内置的、不可构造的对象,它提供了一组静态方法(如 Reflect.get、Reflect.set),用来显式调用 JavaScript 引擎内部的默认操作行为。它不是语法糖,也不是工具库——它是 Proxy 的“默认行为实现层”。
Proxy 和 Reflect 是一对协作关系:Proxy 负责“拦截”,Reflect 负责“转发”。不配合使用,很容易写出有 bug 的代理逻辑。
为什么 set/get 拦截里必须用 Reflect.set 和 Reflect.get?
直接写 target[prop] = value 或 target[prop] 看似简单,但会绕过很多关键语义:
- 忽略属性描述符(比如
writable: false或configurable: false) - 破坏访问器(getter/setter)中的
this绑定 ——this会指向target,而不是代理对象本身 - 跳过原型链查找(
Reflect.get会正确走[[Get]]内部协议,target[prop]不会) - 对私有字段(
#field)直接报错,而Reflect.get(target, prop, receiver)支持 -
settrap 必须返回布尔值(true表示成功),而赋值表达式无返回值,手写容易漏返回或返回错误值
const obj = {
get name() { return this._name || 'Anonymous'; },
set name(v) { this._name = v.toUpperCase(); }
};
const proxy = new Proxy(obj, {
get(target, prop, receiver) {
console.log(GET ${prop});
// ✅ 正确:receiver 保证 this 指向 proxy
return Reflect.get(target, prop, receiver);
// ❌ 错误:this 指向 target,_name 读写失效
// return target[prop];
}
});
console.log(proxy.name); // "Anonymous"(正确)
立即学习“Java免费学习笔记(深入)”;
Reflect 方法参数顺序统一,且全部返回布尔值或结果值
和零散的全局操作(如 delete obj.x、obj instanceof C)不同,Reflect 把所有底层操作都收口为函数调用,参数顺序也高度一致:
- 第一个参数永远是目标对象(
target) - 第二个是属性名(
prop)或类(Constructor)等 - 第三个起是上下文或参数列表(如
receiver、args)
更重要的是:Reflect.deleteProperty 返回 true/false,不会像 delete 操作符在严格模式下对不可配置属性抛错;Reflect.has 也不触发原型上 getter —— 这些都是可控性的体现。
大高朋团购系统是一套Groupon模式的开源团购程序,开发的一套网团购程序,系统采用ASP+ACCESS开发的团购程序,安装超简,功能超全面,在保留大高朋团购系统版权的前提下,允许所有用户免费使用。大高朋团购系统内置多种主流在线支付接口,所有网银用户均可无障碍支付;短信发送团购券和实物团购快递发货等。 二、为什么选择大高朋团购程序系统? 1.功能强大、细节完善 除了拥有主流团购网站功能,更特别支
对比:
-
key in obj→ 可能意外触发原型上的 getter -
Reflect.has(obj, key)→ 安全、静默、可判断
Proxy + Reflect 是响应式、校验、日志等场景的最小可行组合
真实工程中,你几乎不会只用 Proxy 而不用 Reflect。Vue 3 的 reactive()、Zustand 的 proxy middleware、甚至简单的类型校验封装,都依赖这个组合。
典型陷阱写法(错):
set(target, prop, value) {
if (typeof value !== 'string') throw new Error('must be string');
target[prop] = value; // ❌ 绕过描述符、不支持 receiver、没返回值
}
正确写法(推荐):
set(target, prop, value, receiver) {
if (prop === 'name' && typeof value !== 'string') {
throw new Error('name must be string');
}
// ✅ 走标准语义,支持访问器、原型、私有字段、receiver
return Reflect.set(target, prop, value, receiver);
}
注意:receiver 参数不能省略 —— 它确保 setter 内部的 this 指向代理对象,这对依赖 this 的响应式系统至关重要。
真正难的不是写一个 Proxy,而是写一个不破坏原有语义的 Proxy。只要漏掉 receiver、跳过 Reflect、或忽略 deleteProperty/defineProperty 等 trap,所谓“只读”“校验”“响应式”就只是纸糊的。










