proxy 可拦截对象读写操作,比 object.defineproperty 更灵活强大;支持动态属性、未定义属性处理、嵌套对象递归代理及响应式实现,但不能代理原始值且需注意性能与兼容性问题。

Proxy 可以拦截对象的读写操作,实现类似 getter/setter 的功能,但比 Object.defineProperty 更强大、更灵活。
基本用法:拦截 get 和 set
通过 Proxy 构造函数创建代理对象,传入目标对象和处理器(handler)对象。handler 中定义 get 和 set 方法即可拦截属性访问与赋值。
- get(target, prop, receiver):拦截属性读取,target 是原对象,prop 是属性名(可能是字符串或 Symbol),receiver 通常是 proxy 本身(用于正确处理 this)
- set(target, prop, value, receiver):拦截属性设置,返回 true 表示成功,false 或抛异常会失败(严格模式下报错)
例如:
const obj = { name: 'Alice' };
const proxy = new Proxy(obj, {
get(target, prop) {
console.log(`读取属性: ${prop}`);
return target[prop];
},
set(target, prop, value) {
console.log(`设置 ${prop} = ${value}`);
target[prop] = value;
return true; // 必须返回 true
}
});
proxy.name; // 输出“读取属性: name”,返回 'Alice'
proxy.age = 25; // 输出“设置 age = 25”
支持动态属性与不存在的属性
Proxy 不依赖预先定义的属性,能拦截任意属性(包括后续新增、嵌套、Symbol 属性),而 defineProperty 只能对已有属性生效或需提前声明。
- 可统一处理未定义属性:比如返回默认值、触发警告、或委托到其他对象
- 配合 in 操作符或 has() 拦截,还能控制属性是否存在(如隐藏私有字段)
- 对数组索引、length、甚至原型链访问(如 __proto__)也可拦截
示例:为所有未定义属性返回 0
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
const proxy = new Proxy({}, {
get(target, prop) {
return prop in target ? target[prop] : 0;
}
});
console.log(proxy.unknown); // 0
实现响应式数据的核心机制
现代响应式框架(如 Vue 3)用 Proxy 实现数据劫持,关键在于:
- 递归代理嵌套对象:在 get 中检测返回值是否为对象,是则自动 wrap 成新 proxy
- 依赖收集:读取时记录当前副作用函数,写入时触发更新
- 拦截数组方法:重写 push/pop 等方法,或监听 length、索引变化
- 避免无限循环:set 中修改 target 后需确保不重复触发自身 handler(可用 Reflect.set 辅助)
简化版响应式示意:
function reactive(obj) {
return new Proxy(obj, {
get(target, prop) {
track(target, prop); // 收集依赖
const value = target[prop];
return typeof value === 'object' && value !== null
? reactive(value)
: value;
},
set(target, prop, value) {
const result = Reflect.set(target, prop, value);
trigger(target, prop); // 触发更新
return result;
}
});
}
注意事项与常见陷阱
Proxy 虽强大,使用时需注意边界情况:
- 不能代理原始值(null、undefined、string、number 等),只能代理对象
- 代理后原对象仍可直接访问,响应式需始终使用 proxy 实例
- Object.is()、=== 判断时,proxy 和原对象不相等;instanceof 也可能失效
- 某些内置行为(如 Date、RegExp 的内部状态)可能无法完全拦截
- 性能开销略高于 defineProperty,但对大多数场景影响不大
不复杂但容易忽略。










