Proxy 是 JavaScript 中用于拦截并自定义对象基本操作的代理构造函数,支持 get、set、has、deleteProperty、apply、construct、ownKeys、defineProperty、getOwnPropertyDescriptor 等拦截;它仅代理第一层属性,无法拦截私有字段、底层内存操作及部分数组内部方法。
JavaScript 中的 Proxy 是一个内置构造函数,用于创建一个代理对象,从而拦截并自定义对目标对象的基本操作(如读取、赋值、函数调用等)。它不是“替代”对象,而是“包裹”对象,让开发者能在访问或修改对象时插入逻辑。
Proxy 通过 handler(处理器)对象定义拦截行为,每个拦截方法对应一种对象操作。常用且高频的拦截包括:
obj.prop、obj['key'])obj.prop = value),可控制是否允许赋值、做数据校验in 操作符时触发('prop' in obj)delete obj.prop 时触发proxy(...args))new proxy(...) 实例化时触发Object.getOwnPropertyNames()、Object.keys() 或 for...in 循环前触发,可过滤/添加键名Object.defineProperty() 时触发Object.getOwnPropertyDescriptor() 时触发常用于响应式系统(如简易 Vue 响应式原理):
const data = { count: 0 };
const handler = {
get(target, key) {
console.log(`读取 ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`设置 ${key} = ${value}`);
target[key] = value;
// 这里可以触发更新视图
updateView();
return true;
}
};
const proxy = new Proxy(data, handler);
proxy.count++; // 输出:读取 count → 设置 count = 1
对象需递归代理(或结合 Reflect 使用)Reflect.get() / Reflect.set() 替代直接访问,保持默认行为并避免陷阱=== 与原对象相等(proxy !== data)Object.isExtensible(proxy))会直接作用于 target,除非显式在 handler 中拦截以下操作无法被 Proxy 直接拦截:
get,但只要用了 proxy.xxx 就一定会进 get;真正无法拦截的是底层内存操作或引擎内部行为obj.__proto__)—— 已废弃,且不推荐;应使用 Object.getPrototypeOf() 等 API,这些可被对应 trap 拦截length 属性变更、索引越界赋值(如 arr[100] = 1)会被 set 拦截,但部分数组方法(push、pop)内部行为较复杂,需配合 get 拦截其方法访问再包装#field)无法被 Proxy 观察,这是语言层面限制