reflect.get 和 reflect.set 是 es6 提供的安全属性访问与赋值方法,支持 receiver 绑定、symbol 键、继承访问且不报错;常与 proxy 搭配实现拦截与转发,参数一致便于统一抽象,广泛用于响应式系统。

Reflect.get 和 Reflect.set 是 ES6 提供的一对配套操作,用于安全、可拦截地读取和设置对象属性,常与 Proxy 搭配使用,也适用于需要统一处理属性访问逻辑的场景。
替代点号和方括号访问,支持动态键与默认值
相比 obj.key 或 obj[key],Reflect.get 能显式指定 receiver(即 this 绑定),并支持在原型链上查找。它还能配合 Proxy 的 get trap 使用,实现属性读取的集中控制。
- 基本用法:
Reflect.get(obj, 'prop', receiver)—— 第三个参数决定 getter 中的this值 - 支持 Symbol 键、计算属性名、继承属性访问,且不会因访问 undefined 对象而报错(返回
undefined) - 可封装为带默认值的读取工具,例如:
Reflect.get(obj, key) ?? defaultValue
与 Reflect.set 配合实现受控赋值
Reflect.set 同样接受 target、key、value、receiver 四个参数,返回布尔值表示是否成功(区别于 obj[key] = val 总是返回 value)。二者参数结构一致,便于统一抽象。
- 赋值前可校验类型、权限或触发副作用,例如日志、响应式通知、只读拦截
- 在 Proxy handler 中,通常用
Reflect.get(target, key, receiver)和Reflect.set(target, key, value, receiver)转发操作,避免硬编码逻辑 - receiver 参数确保 setter 中的
this正确指向原始调用对象(尤其涉及类实例或原型方法时)
在 Proxy 中形成完整访问闭环
Proxy 的 get/set trap 若直接操作目标对象,容易绕过拦截逻辑;而使用 Reflect 方法可保证行为一致性,并支持递归代理。
- 标准写法示例:
- 这样既保留了原生行为,又注入了自定义逻辑,且能正确处理 getter/setter、Symbol 属性、继承关系
- 若需拦截失败(如禁止写入),set trap 中可返回 false,此时
Reflect.set仍会执行但 trap 可中断流程
const handler = {
get(target, key, receiver) {
console.log('读取:', key);
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
console.log('设置:', key, value);
return Reflect.set(target, key, value, receiver);
}
};
注意陷阱:receiver 不等于 target
receiver 是属性访问发生的上下文对象(通常是 proxy 实例本身),而非被操作的原始 target。忽略它可能导致 this 绑定错误,尤其在访问带有 this 依赖的 getter/setter 时。
- 错误写法:
Reflect.get(target, key)—— 缺失 receiver,getter 内部 this 指向 target,而非调用者 - 正确做法:始终传入 receiver,尤其在 Proxy 中应使用 trap 的第四个参数
- 常见场景:Vue 3 响应式系统、MobX、自定义数据绑定库都依赖这一机制维持上下文一致性










