能实现,但需三方面协同:监听索引赋值(识别数字键、处理越界与追加)、拦截length属性(捕获截断与扩容)、代理原生方法(如push/splice)并通知变更,同时用WeakMap缓存子对象防内存泄漏。
能实现,但不能只靠默认的 set 拦截器——必须同时处理索引赋值、length 修改、以及原生数组方法(如 push、splice)引发的隐式变更,三者缺一不可。
监听索引写入:捕获所有数字键赋值
数组的 arr[0] = x、arr[100] = y 等操作会触发 set(target, prop, value),其中 prop 是字符串形式的索引(如 "0" 或 "100")。需做两件事:
- 用
/^\d+$/.test(prop)判断是否为合法非负整数索引(排除"-1"、"2.5"、"length") - 将
prop转为数值后,与target.length比较:若idx >= target.length && idx !== target.length,即为越界写入,可警告或拒绝 - 无论是否越界,只要成功写入(包括追加
arr[arr.length] = v),都应触发变更通知
拦截 length 属性:识别清空、截断与扩容意图
arr.length = 0、arr.length = 5 这类操作直接走 set,prop === "length"。这是监控数组“结构性变化”的关键入口:
安全更新和维护 CLI Proxy API(CPA)部署与配置。用于 CPA 镜像升级、配置变更、认证目录兼容修复、上线验证与回滚。适用于用户提到“CPA 更新/升级/配置改了/容器重建/回滚”等场景。
- 若新
value < target.length:表示截断,旧元素被删除,应通知length-shrink及受影响索引范围 - 若新
value > target.length:表示稀疏扩容(如arr.length = 10后arr[9]才存在),可标记为length-grow - 必须调用
Reflect.set(target, prop, value)完成真实赋值,再执行自定义逻辑
代理原生数组方法:覆盖 push/pop/splice 等“静默变更”
像 arr.push(x)、arr.splice(0,1) 这些方法本身不触发 set,但会修改索引和 length。解决方式是在 get 拦截器中对方法名做代理:
- 预设需拦截的方法列表:
["push", "pop", "shift", "unshift", "splice", "sort", "reverse"] - 当访问
proxy.push时,在get中返回一个包装函数:先调用原生方法,再统一触发update("array-method", { method, args, oldLen, newLen }) - 注意用
Reflect.get(target, prop, receiver)获取原始方法,避免递归死循环 - 对
push返回的新长度、splice返回的删除项等,保持原语义不破坏调用方逻辑
防重复代理与内存泄漏:WeakMap 缓存是刚需
若数组内含对象(如 arr = [{id:1}, {id:2}]),且需深度监听其属性,每次读取 proxy[0] 都可能生成新 Proxy。不控制就会内存暴涨:
- 声明
const cache = new WeakMap()存储已代理的子对象/子数组 - 在
get中:若value是对象且未缓存,用相同 handler 创建新 Proxy 并存入 cache;否则直接返回缓存实例 - WeakMap 自动随原始对象回收,比 Map 更安全,也避免 GC 障碍

















