Proxy 拦截对象属性访问的核心是通过 get/set trap 在读写时插入逻辑而不修改原对象,需用 Reflect 转发以保原型链,且仅代理第一层、需手动处理嵌套、私有字段和 Symbol 属性。

用 Proxy 拦截对象属性访问,核心是创建一个代理层,在读取(get)或写入(set)属性时插入自定义逻辑,而不改动原对象。
基础写法:get 和 set 是最常用拦截点
每次访问 proxy.prop 或赋值 proxy.prop = value,都会触发对应 trap:
- get(target, prop, receiver):用于控制“怎么读”。比如返回默认值、拒绝敏感字段、做日志记录
- set(target, prop, value, receiver):用于控制“怎么写”。比如校验数据范围、禁止修改、同步更新其他字段
- 务必用
Reflect.get()或Reflect.set()转发操作,否则可能破坏原型链、getter 绑定或继承行为
常见实用场景
不需要复杂配置,几个典型用法就能解决多数问题:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
- 限制敏感字段读取:在 get 中判断 prop === 'password',直接抛错或返回 undefined
- 数据范围约束:set 里检查 value 是否在合理区间(如 age 只允许 0–150),越界则自动修正
- 提供默认值:get 中发现 target 没有该属性,返回预设值而非 undefined
- 访问日志与审计:在 get/set 里打印操作时间、字段名、用户上下文等信息
容易忽略的关键细节
Proxy 行为看似简单,但几处细节直接影响是否可靠:
- Proxy 只代理第一层,嵌套对象不会自动被拦截。需要手动递归代理,或按需包装
- 私有字段(#field)和 Symbol 属性不会被默认 get/set 捕获,必须显式处理
-
in操作符走的是 has trap,不是 get;枚举(for...in、Object.keys)依赖 ownKeys,不实现它们会导致行为不一致 - receiver 参数影响 this 绑定和原型查找起点,尤其在调用 getter 或继承方法时不能省略
一个完整可运行的例子
对 person 对象的 age 做安全赋值:
const person = { age: 0 };
const proxy = new Proxy(person, {
set(target, prop, value) {
if (prop === 'age') {
target[prop] = Math.min(150, Math.max(0, value));
return true;
}
target[prop] = value;
return true;
},
get(target, prop) {
return Reflect.get(target, prop);
}
});
proxy.age = 200; // 实际设为 150
proxy.age = -5; // 实际设为 0
console.log(proxy.age); // 0

















