JavaScript Proxy 是用于创建对象代理的构造函数,通过 handler 中的 traps 拦截属性访问、修改等操作;支持 get、set、has 等常用陷阱,广泛应用于响应式系统、数据校验、API 代理等场景,但需注意嵌套对象需手动递归代理及性能开销。

JavaScript Proxy 是一个用于创建对象代理的构造函数,它能让你在访问、修改、删除对象属性等操作时插入自定义逻辑——也就是“拦截”。它不改变原对象,而是包装一层代理,所有对代理的操作都会经过你定义的“陷阱(traps)”函数处理。
Proxy 的基本用法:创建代理对象
要使用 Proxy,你需要两个参数:目标对象(target)和处理器对象(handler)。handler 里定义各种拦截方法,比如 get、set、has、deleteProperty 等。
最简单的例子是拦截读取属性:
const target = { name: 'Alice', age: 30 };
const handler = {
get(obj, prop) {
console.log(`正在读取属性: ${prop}`);
return prop in obj ? obj[prop] : '默认值';
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // 输出:正在读取属性: name → 'Alice'
console.log(proxy.city); // 输出:正在读取属性: city → '默认值'
常用拦截操作与对应 trap
每个 trap 对应一种对象操作。掌握几个高频 trap 就能覆盖大部分场景:
立即学习“Java免费学习笔记(深入)”;
-
get(target, prop, receiver):拦截读取属性,比如
obj.x、obj['x'],也包括in操作符(需配合hastrap) -
set(target, prop, value, receiver):拦截赋值,比如
obj.x = 1;返回true表示设置成功,否则报错(严格模式下) -
has(target, prop):拦截
prop in obj,可隐藏属性或模拟“不存在” -
deleteProperty(target, prop):拦截
delete obj.x,可禁止删除或触发清理逻辑 -
ownKeys(target):拦截
Object.keys()、for...in等枚举操作,控制哪些属性可见
实际能做什么?几个典型用途
Proxy 不只是玩具,它支撑了 Vue 3 响应式、状态库、验证层、日志监控等真实功能:
-
数据校验:在
set中检查类型或范围,非法值直接拒绝或转换 -
响应式系统:在
get中收集依赖,在set中触发更新(Vue 3 的 reactive 底层就是 Proxy) -
私有属性模拟:用
get和ownKeys隐藏以下划线开头的属性,不让外部看到 -
API 调用代理:把对象属性访问转成 HTTP 请求,比如
api.users.list()自动发起 GET /users
注意点:Proxy 的限制与边界
Proxy 很强大,但不是万能的:
- 只代理**直接操作**:对代理对象的嵌套对象不会自动代理,需要递归包装或懒代理(lazy proxy)
- 无法拦截普通对象的原型操作(如
obj.__proto__),但可用getPrototypeOf/setPrototypeOftrap 拦截相关行为 - 某些内置行为绕过 trap:比如
Object.getOwnPropertyDescriptor(proxy, 'x')仍读原始描述符,除非你重写getOwnPropertyDescriptor - 性能开销存在:每次属性访问都多一层函数调用,高频场景需权衡
基本上就这些。Proxy 的核心就是“用 handler 定义你想干预的行为”,写清楚 trap,剩下的交给 JS 引擎调度。不复杂但容易忽略细节——比如忘记返回值、没处理 receiver、或忘了递归代理深层对象。











