代码重构中应优先对跨组件配置、多函数读写缓存、响应式源数据及测试fixture进行深拷贝,现代环境用structuredClone(),旧环境或复杂数据用Lodash cloneDeep(),避免JSON序列化陷阱并配合不可变更新模式。

在代码重构中,把共享的可变状态转为安全的独立副本,核心是用深拷贝切断引用链,避免副作用。这不是简单复制数据,而是让每个模块、函数或组件拿到的是“专属副本”,改它不影响别人。
明确哪些状态需要深拷贝
优先处理以下几类共享可变状态:
- 跨组件/模块传递的配置对象(如表单初始值、筛选条件)
- 被多个函数读写的状态缓存(如本地计算结果、临时聚合数据)
- 响应式系统中需派生新状态的源数据(如 Vue 的 computed 或 React 的 useMemo 输入)
- 测试中反复修改的 fixture 数据,防止用例间污染
按环境选对深拷贝方法
不能统一用一种方式,要结合运行时和数据特征:
- 现代浏览器 + 纯数据(无函数、无 undefined)→ 直接用 structuredClone(),支持 Date、Map、Set、循环引用,一行搞定且语义清晰
- Node.js v18.15+ 或 Chrome 98+/Firefox 94+ → 同样首选 structuredClone(),无需引入依赖
- 需兼容旧环境,或数据含函数/Symbol/undefined → 用 Lodash 的 _.cloneDeep(),经多年验证,覆盖类型全,错误边界处理稳
- 重构中要精细控制(比如过滤敏感字段、跳过某些 key、保留原型)→ 手写递归函数,配合 WeakMap 防循环引用,示例中 seen 参数就是关键
重构时避开常见陷阱
深拷贝不是加一行代码就完事,要注意三处易错点:
立即学习“Java免费学习笔记(深入)”;
- 别在循环体或高频路径里无脑深拷贝大对象,性能会掉——先判断是否真需要拷贝,比如用 Object.is() 或浅比较确认值已变更再拷贝
- JSON.parse(JSON.stringify()) 看似方便,但 Date 变字符串、RegExp 变空对象、undefined 消失,重构后逻辑可能静默出错,除非你 100% 控制输入结构
- DOM 节点、Promise、WeakMap、window 对象等无法被 structuredClone 或 cloneDeep 复制,遇到这类值应提前剥离或换设计,比如把 DOM 引用改为 ID 字符串
配合不可变模式一起用效果更好
深拷贝只是起点,重构中建议搭配不可变更新习惯:
- 用结构化赋值替代直接修改:不写 state.user.name = 'Alice',而写 { ...state, user: { ...state.user, name: 'Alice' } }
- 数组操作用 map/filter/concat,不用 push/splice
- 把深拷贝封装成工具函数(如 safeClone(obj)),内部自动选 method,并加开发环境警告提示不支持的类型


















