JavaScript深度克隆推荐structuredClone()(现代环境)、JSON序列化(仅POJO)、手写递归(需WeakMap防循环)或Lodash的cloneDeep()(工程首选),需注意类型支持与引用一致性。

JavaScript 没有原生的“深度克隆”函数,Object.assign() 和展开运算符 {...obj} 都只做浅拷贝,嵌套对象/数组仍共享引用——这是绝大多数意外修改的根源。
用 structuredClone()(推荐但注意兼容性)
这是目前最标准、语义最清晰的深度克隆方案,能正确处理 Date、Map、Set、ArrayBuffer 等内置类型,且自动跳过不可枚举属性和函数。
- 仅支持现代环境:Chrome 98+、Firefox 94+、Edge 98+;Node.js 17.0+(需启用
--harmony-structured-clone标志,18.12+ 默认开启) - 不支持
RegExp、Error、Promise、function、undefined、Symbol键——遇到会直接抛错:DataCloneError - 示例:
const clone = structuredClone(originalObj);
用 JSON.parse(JSON.stringify(obj))(快但限制极多)
这是最常被误用的“伪深克隆”,本质是序列化再反序列化,只适用于纯数据对象(POJO)。
- 会丢失:
Date(变成字符串)、undefined(被忽略)、function(被忽略)、RegExp(变成空对象)、NaN/Infinity(变成null) - 无法处理循环引用,直接报错:
TypeError: Converting circular structure to JSON - 对
BigInt报错:TypeError: Do not know how to serialize a BigInt - 仅适合临时调试或已知结构简单、无副作用的数据
手写递归克隆(可控但易漏边界)
当需要支持 RegExp、Date、Map、Set 或处理循环引用时,必须自己实现。关键不是“写得短”,而是覆盖类型判断和引用缓存。
本文档主要讲述的是j2me3D游戏开发简单教程; 如今,3D图形几乎是任何一部游戏的关键部分,甚至一些应用程序也通过用3D形式来描述信息而获得了成功。如前文中所述,以立即模式和手工编码建立所有的3D对象的方式进行开发速度很慢且很复杂。应用程序中多边形的所有角点必须在数组中独立编码。在JSR 184中,这称为立即模式。希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
立即学习“Java免费学习笔记(深入)”;
- 必须用
WeakMap缓存已克隆的对象,否则循环引用会栈溢出 - 区分
Array.isArray()和typeof obj === 'object',避免把null当对象处理 -
new obj.constructor()不安全:自定义类可能没有无参构造函数,或构造函数有副作用 - 更稳妥的做法是按类型分别处理:
if (obj instanceof Date)→new Date(obj.getTime()),if (obj instanceof RegExp)→new RegExp(obj.source, obj.flags)
Lodash 的 _.cloneDeep()(工程首选)
在真实项目中,除非有强约束(如不能引入依赖),否则直接用 _.cloneDeep() 是最省心的选择。
- 支持所有常见类型:
Date、RegExp、Map、Set、TypedArray、甚至Buffer(Node.js) - 自动检测并处理循环引用,不报错也不卡死
- 可被 Tree-shaken(ESM 导入下),体积影响可控:
import { cloneDeep } from 'lodash-es'; - 注意:不要用
lodash全量包,它默认是 CommonJS,破坏 ESM 构建链路
真正麻烦的从来不是“怎么克隆”,而是“克隆后谁负责维护引用一致性”。比如克隆一个含事件监听器或 DOM 节点的对象,深克隆反而会让逻辑断裂——这时候该考虑的往往不是克隆,而是重构数据流或使用不可变更新模式。










