json.parse(json.stringify(obj))仅适用于纯数据对象,会丢失函数、undefined、symbol、date、regexp等类型,不支持循环引用;可靠替代方案包括structuredclone(现代环境)、lodash的_.clonedeep(兼容老环境)或自定义递归实现。

因为简单深拷贝方案往往只解决“数据隔离”这一个表层问题,却对原型污染、特殊类型丢失、循环引用、性能失控等生产级风险视而不见。
原型污染:看似安全的拷贝,实则改了全局
像 JSON.parse(JSON.stringify(obj)) 或旧版 lodash.cloneDeep({"__proto__": {"isAdmin": true}},目标对象的 __proto__ 就会被直接写入,污染 Object.prototype——所有后续创建的对象都会继承 isAdmin: true,权限系统瞬间崩塌。
- 仅过滤顶层
__proto__不够,攻击者可用"a.b.__proto__.c"绕过 -
Object.assign({}, obj)即使不递归,若obj已被污染,新对象仍继承危险原型 - 真正安全的克隆必须在写入前扫描路径,或用
Object.create(null)切断原型链
类型丢失:拷贝完才发现功能没了
很多“一键深拷贝”方案本质是序列化再反序列化,天然丢弃函数、Date、RegExp、undefined、Map、Set 等非 JSON 可表示类型。
-
JSON.parse(JSON.stringify({ now: new Date(), re: /abc/g }))→{ now: null, re: null } - 传给图表库的数据里日期变字符串,时间轴直接错乱
- 表单校验规则里的正则函数消失,校验逻辑彻底失效
循环引用与性能陷阱:内存爆掉才报警
手写递归或未做优化的工具,在遇到循环引用(如父子关系对象、事件监听器闭环)时可能无限递归,或生成超大临时结构拖垮服务。
- 没做引用缓存的深拷贝,同一对象被反复克隆多次,内存占用翻倍增长
- 拷贝一个含 10 层嵌套、500 个节点的树形配置,耗时从几毫秒飙升到 2 秒以上
- 高频调用场景(如实时消息处理)下,GC 压力陡增,引发卡顿甚至 OOM
状态管理失联:副本和源数据“藕断丝连”
某些框架或库内部维护私有状态(如 Vue 的响应式代理、React 的 fiber 节点、immer 的 draft),简单深拷贝会破坏其内部结构,导致响应失效或更新丢失。
- 对 Vue reactive 对象直接
structuredClone,返回普通对象,失去响应性 - 用
lodash.cloneDeep拷贝 Redux store state,中间件可能无法识别新对象 - 未用 immer 的
produce而直接修改深拷贝后的 draft,变更不会同步到原始 state











