Proxy是一种在目标对象前架设拦截层的元编程机制,用于对外部访问进行过滤、改写和监控,不修改原对象,支持get、set、apply等13种操作拦截,适用于任何对象且无需继承。

Proxy 是一种通用的增强机制,不是给对象“打补丁”,而是为访问行为本身加一层可控的拦截。它不修改原对象,也不依赖继承或接口实现,而是通过代理层重定义操作语义,从而在方法调用、属性读写等环节注入逻辑。
明确增强目标:是调用过程,不是方法本身
Proxy 增强的是“对方法的访问行为”,而非方法体内部代码。比如你调用 obj.doWork(),Proxy 拦截的是“这次调用”这个动作——可在此前后加日志、校验、缓存判断、权限检查,甚至替换返回值或阻止执行。
- 不能直接改写
doWork的源码逻辑(那是装饰器或子类的事) - 但能控制:谁在什么时候调用它、传了什么、是否允许执行、结果要不要包装
- 适用于任何对象(包括无原型、无 class 的 plain object)
核心写法:handler 中定义拦截点
创建 Proxy 时传入的 handler 对象,决定哪些操作可被增强。常用拦截项有:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- apply:拦截函数调用(适用于代理函数对象)
- get:拦截属性读取(可用于懒加载、响应式取值)
- set:拦截属性赋值(可用于数据校验、变更通知)
- has、deleteProperty、ownKeys 等:分别控制 in 操作、delete、Object.keys() 等行为
例如,为一个计算器对象增强所有方法调用的日志与耗时统计:
const calc = { add: (a, b) => a + b, mul: (a, b) => a * b };
const loggedCalc = new Proxy(calc, {
apply(target, thisArg, args) {
console.time(`call ${target.name || 'anonymous'}`);
const result = target.apply(thisArg, args);
console.timeEnd(`call ${target.name || 'anonymous'}`);
return result;
}
});
// 注意:calc 必须是函数才能触发 apply;若 calc 是普通对象,需用 get + typeof fn 判断后转 call实际可扩展的方向
不是“加功能”,而是“控流程”。常见落地场景包括:
- 参数预处理:自动转换类型、填充默认值、过滤敏感字段
- 访问控制:根据用户角色决定是否允许调用某方法(如管理员专属 API)
- 缓存代理:相同参数调用直接返回缓存结果,避免重复计算
- 错误兜底:捕获方法异常,统一返回 fallback 值或重试逻辑
- 链路追踪:注入 traceId,记录调用路径与上下文
注意边界:Proxy 不是万能胶
它强大但有约束:
- 仅对“被代理对象上的操作”生效;原始引用一旦脱离 Proxy,就不再受控
- 无法拦截私有字段(#field)、不可枚举属性(除非 ownKeys 显式暴露)
- 性能略低于直调——每次访问都经过 handler,高频场景需权衡
- 不能代理非对象值(null、number、string 字面量),必须包装成对象

















