使用Proxy检测全局对象及其子属性变动无日志输出问题求助
问题原因
- 你创建的
scopeProxy代理实例没有挂载回全局对象,后续所有修改操作依然作用在原始window.app对象上,不会触发Proxy的拦截钩子。Proxy的拦截逻辑仅对代理实例生效,不会修改原对象本身的行为。 - 默认Proxy只能监听对象的直接属性变更,无法自动拦截嵌套子属性(比如
app.reports.name)的修改,需要手动给嵌套的对象/数组也包裹代理。
修复实现
const scopeHandler = { set: function(obj, prop, value) { // 新旧值相同则跳过日志输出 if (obj[prop] === value) return true console.log(`${prop} changed from ${obj[prop]} to ${value}`); // 新赋值为引用类型时自动包裹代理 obj[prop] = typeof value === 'object' && value !== null ? new Proxy(value, scopeHandler) : value; return true; }, get: function(obj, prop) { const value = obj[prop] // 读取引用类型属性时提前包裹代理,保证后续子属性修改可被监听 if (typeof value === 'object' && value !== null) { return new Proxy(value, scopeHandler) } return value } }; // 递归给所有嵌套属性添加代理 function createDeepProxy(target, handler) { if (typeof target !== 'object' || target === null) return target // 先处理原有嵌套属性 for (const key in target) { target[key] = createDeepProxy(target[key], handler) } return new Proxy(target, handler) } // 将代理实例直接挂载到window.app,后续所有操作都会走代理逻辑 window.app = createDeepProxy(window.app, scopeHandler);
注意事项
- 如果之前的代码有提前将
window.app的引用存储到其他变量的场景,需要将这些引用同步替换为代理实例,否则操作旧引用依然不会触发监听。 - 该实现可兼容数组类型的监听,包括索引修改、
length属性变更的场景。
内容的提问来源于stack exchange,提问作者eozzy
相关产品推荐
相关产品推荐

