结构共享是绕开深拷贝的不可变更新方案,通过复用未变更子结构、仅新建差异节点来实现高效内存与时间开销。

结构共享(Structural Sharing)不是替代深拷贝的“新深拷贝”,而是绕开深拷贝的思路——它通过复用未变更的子结构,只创建差异部分的新节点,实现逻辑上的“不可变更新”,同时将内存与时间开销压到最低。
核心原理:共享不变,只新建变化分支
传统深拷贝是“全量复制一棵树”,而结构共享像 Git 提交:每次修改只生成新快照,和旧快照共用大量相同节点。适用于树形/嵌套数据结构(如状态树、AST、配置对象),前提是数据按不可变方式使用。
- 所有更新操作(如 set、push、merge)返回新对象,原对象保持不变
- 底层自动追踪哪些字段未变,直接复用其引用,不分配新内存
- 无需递归遍历全部字段,时间复杂度接近 O(log n) 或 O(1)(取决于数据结构实现)
主流结构共享库及适用场景
Immutable.js(JS):提供 Map、List、Set 等持久化集合。内部用哈希数组映射树(HAMT)实现,10万级元素下更新性能稳定,比 JSON.parse/stringify 快 20 倍以上,且支持循环引用与函数保留。
Immer(JS):语法最友好——允许你用“直接修改”的写法(如 draft.items.push(x)),底层自动转为结构共享更新。适合 React/Vue 状态管理,零学习成本切入。
Scala’s PersistentVector / Clojure’s data structures(JVM):工业级验证,支持并发安全读取+单线程写入,GC 友好,广泛用于高吞吐中间件。
rust-immutable(Rust):基于 RRB-Tree,零运行时开销,所有权模型天然契合结构共享语义,适合嵌入式或实时系统。
关键落地要点
结构共享不是开箱即用的银弹,需配合约定才能发挥价值:
- 禁止对原始对象做突变(mutate),所有更新必须走库提供的 API 或 produce 函数
- 避免混用结构共享对象与普通对象——例如不要把 Immer draft 传给期望可变数组的第三方函数
- 小而浅的数据(如仅 2–3 层、无重复子结构)不必强上;此时手动浅拷贝 + 关键字段深拷贝更轻量
- 调试时善用库自带的 is() 或 equals() 工具函数比对引用相等性,确认共享是否生效
性能对比的真实边界
在含 5 层嵌套、1000+ 节点的对象上实测(Chrome 124 / Go 1.23):
- JSON 深拷贝:~8.2ms,内存分配 1.6MB
- 递归反射深拷贝:~4.7ms,内存分配 920KB
- Immer produce 更新(仅改一个叶子字段):~0.03ms,内存分配 12KB
- Immutable.Map.set(...):~0.01ms,内存分配 4KB
差距来自根本差异:后两者不复制整棵树,只新建路径上的 3–5 个节点,其余数百节点全部复用。










