Proxy能够监听到对象中的对象的引用吗?
简短结论原生的new Proxy(target, handler)只能代理「它直接包裹的那一层对象」对target内部的嵌套对象默认是透传的——返回的是裸对象后续操作完全逃逸监听。为什么会听不到嵌套对象const obj { a: { b: 1 } }; const proxy new Proxy(obj, { get(t, k) { console.log(get, k); return Reflect.get(t, k); }, set(t, k, v) { console.log(set, k, v); return Reflect.set(t, k, v); } }); proxy.a.b 99; // 只触发了一次 get(a)返回的是原始裸对象 { b: 1 } // set(b) 永远不会触发执行proxy.a.b 99的过程先走get(proxy, a)→ 拿到obj.a原始{ b: 1 }不是 Proxy然后对这个裸对象执行.b 99→ 跟 Proxy 毫无关系所以不是 Proxy 能力不够而是它根本没有机会介入第二步——因为第一步返回的就不是代理对象。✅ 解法递归代理Proxy Membrane 模式核心思路在get拦截器中凡是读到的值是对象就再给它套一层 Proxy让整条访问链上的每一层都是代理过的function deepProxy(target, handler) { // 缓存避免重复代理 处理循环引用 const cache new WeakMap(); function makeProxy(obj) { if (obj null || typeof obj ! object) return obj; if (cache.has(obj)) return cache.get(obj); const proxy new Proxy(obj, { get(t, key, receiver) { const val Reflect.get(t, key, receiver); // 读到子对象 → 递归代理后返回 return (val ! null typeof val object) ? makeProxy(val) : val; }, set(t, key, value, receiver) { const oldVal t[key]; const result Reflect.set(t, key, value, receiver); handler?.onChange?.({ type: SET, path: key, oldValue: oldVal, newValue: value }); return result; }, deleteProperty(t, key) { const had key in t; const oldVal t[key]; const result Reflect.deleteProperty(t, key); if (had) handler?.onChange?.({ type: DELETE, path: key, oldValue: oldVal }); return result; } }); cache.set(obj, proxy); return proxy; } return makeProxy(target); }使用效果const state deepProxy({ a: { b: 1 }, list: [10, 20] }, { onChange: ({ type, path, oldValue, newValue }) console.log([${type}] ${path}:, oldValue, →, newValue) }); state.a.b 99; // ✅ 能捕获(经过递归代理的 a 的 set 触发) state.list.push(30); // ⚠️ 数组的 push 本质是方法调用set trap 不一定按你想的方式触发 state.a { c: 2 }; // ✅ 外层 set 正常捕获替换整个子对象引用两种引用变化要区分清楚场景能否被外层 Proxy 的set捕获说明proxy.a { c: 2 }替换整个子对象引用✅能​这是 proxy 自身的属性赋值走set(proxy, a, ...)proxy.a.b 99修改子对象内部属性❌不能除非递归代理操作的是子对象外层 proxy 根本碰不到proxy.a proxy.a把子对象重新赋回✅ 能触发 set虽然值没变但赋值行为本身被拦截⚠️ 几个容易踩的坑数组的push、pop等方法它们内部会读写length走的是方法调用路径而非简单set做响应式系统时通常需要额外处理Array的陷阱更复杂Vue 3 用的也不是纯递归 Proxy 这么简单必须用receiver传进Reflect.get如果对象上有 getter 或原型链继承漏掉 receiver 会导致this指向错误// ✅ 正确 const val Reflect.get(t, key, receiver); // ❌ 危险 const val t[key];typeof null object​ → 判断时一定要加 value ! null性能每次get都判断可能创建 Proxy不加缓存的话同个引用被访问 N 次就产生 N 个 Proxy 实例。用WeakMap做缓存是标准做法一句话总结Proxy 本身是单层的——它只看守你交给它的那扇门。​ 想监听对象中的对象就得在get里把每个子对象也变成 Proxy即 Proxy Membrane / 深代理这也就是 Vue 3 的reactive()背后的核心思想。Proxy 不是不能是需要你主动递归地铺网。

相关新闻

Mac版Navicat无限试用三步解决方案:告别14天限制的终极指南

Mac版Navicat无限试用三步解决方案:告别14天限制的终极指南

Mac版Navicat无限试用三步解决方案:告别14天限制的终极指南 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac 你是否…

2026/6/28 16:06:20阅读更多 →
VisualCppRedist AIO:Windows软件依赖问题的终极解决方案

VisualCppRedist AIO:Windows软件依赖问题的终极解决方案

VisualCppRedist AIO:Windows软件依赖问题的终极解决方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 当您遇到"MSVCP140.dll缺失"、&q…

2026/6/28 17:32:02阅读更多 →
3步打造您的专属PS3游戏库:IRISMAN让游戏管理变得如此简单

3步打造您的专属PS3游戏库:IRISMAN让游戏管理变得如此简单

3步打造您的专属PS3游戏库:IRISMAN让游戏管理变得如此简单 【免费下载链接】IRISMAN All-in-one backup manager for PlayStation3. Fork of Iris Manager. 项目地址: https://gitcode.com/gh_mirrors/ir/IRISMAN 想象一下这样的场景:您的PS3硬盘…

2026/6/28 17:45:55阅读更多 →
2026年最实用的 10 个 AI Prompt 模板:覆盖工作、学习、创作

2026年最实用的 10 个 AI Prompt 模板:覆盖工作、学习、创作

2026年最实用的 10 个 AI Prompt 模板:覆盖工作、学习、创作 2026年,会用AI已经不等于会写一句“帮我总结一下”。真正高效的Prompt不是魔法咒语,而是一套可复用的工作指令:明确角色、任务、上下文、约束、输出格式、样例和检查标…

2026/6/28 20:00:36阅读更多 →
终极罗技鼠标宏配置指南:告别后坐力困扰的完整解决方案

终极罗技鼠标宏配置指南:告别后坐力困扰的完整解决方案

终极罗技鼠标宏配置指南:告别后坐力困扰的完整解决方案 【免费下载链接】logitech-pubg PUBG no recoil script for Logitech gaming mouse / 绝地求生 罗技 鼠标宏 项目地址: https://gitcode.com/gh_mirrors/lo/logitech-pubg 还在为绝地求生中枪口难以控制…

2026/6/28 20:00:36阅读更多 →
ZYNQ启动流程深度解析:从BootROM到应用程序加载

ZYNQ启动流程深度解析:从BootROM到应用程序加载

1. ZYNQ启动流程全景概览 第一次接触ZYNQ的开发者往往会被其复杂的启动流程困扰。作为同时包含ARM处理器和FPGA的可编程SoC,ZYNQ的启动过程确实比传统单片机复杂得多。但理解这个过程对后续开发至关重要——就像开车需要知道发动机如何点火一样。 ZYNQ的启动可以想…

2026/6/28 20:00:36阅读更多 →
MADQN实战:从独立学习到集中协作的算法演进与性能对比

MADQN实战:从独立学习到集中协作的算法演进与性能对比

1. MADQN基础概念与协作场景解析 多代理深度Q网络(MADQN)是传统DQN在多智能体环境中的自然延伸。想象一下足球场上11名队员的配合——每个球员既要独立判断跑位,又要考虑队友的位置和对手的防守策略。MADQN解决的就是这类需要个体决策与群体协…

2026/6/28 20:00:36阅读更多 →
如何为洛雪音乐配置最佳音源:3分钟解锁全网无损音乐

如何为洛雪音乐配置最佳音源:3分钟解锁全网无损音乐

如何为洛雪音乐配置最佳音源:3分钟解锁全网无损音乐 【免费下载链接】lxmusic- lxmusic(洛雪音乐)全网最新最全音源 项目地址: https://gitcode.com/gh_mirrors/lx/lxmusic- 你是否厌倦了在不同音乐平台间来回切换寻找歌曲?是否因为版权限制无法听…

2026/6/28 20:00:36阅读更多 →
ParsecVDisplay:解锁Windows虚拟显示器潜能的终极解决方案

ParsecVDisplay:解锁Windows虚拟显示器潜能的终极解决方案

ParsecVDisplay:解锁Windows虚拟显示器潜能的终极解决方案 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 你是否曾经因为物理显示器的限制而感到束手无策&#xff1f…

2026/6/28 19:50:11阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/6/28 0:08:01阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/6/28 0:08:01阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/6/28 0:08:01阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/6/28 0:08:01阅读更多 →