如何深度克隆对象javascript_有哪些可行的方法【教程】

8次阅读

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

如何深度克隆对象javascript_有哪些可行的方法【教程】

javascript 没有原生的“深度克隆”函数,Object.assign() 和展开运算符 {...obj} 都只做浅拷贝,嵌套对象/数组仍共享引用——这是绝大多数意外修改的根源。

structuredClone()(推荐但注意兼容性)

这是目前最标准、语义最清晰的深度克隆方案,能正确处理 dateMapSetArrayBuffer 等内置类型,且自动跳过不可枚举属性和函数。

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
  • 仅适合临时调试或已知结构简单、无副作用的数据

手写递归克隆(可控但易漏边界)

当需要支持 RegExpDateMapSet 或处理循环引用时,必须自己实现。关键不是“写得短”,而是覆盖类型判断和引用缓存。

立即学习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() 是最省心的选择。

  • 支持所有常见类型:DateRegExpMapSetTypedArray、甚至 Buffernode.js
  • 自动检测并处理循环引用,不报错也不卡死
  • 可被 Tree-shaken(ESM 导入下),体积影响可控:import { cloneDeep } from 'lodash-es';
  • 注意:不要用 lodash 全量包,它默认是 CommonJS,破坏 ESM 构建链路

真正麻烦的从来不是“怎么克隆”,而是“克隆后谁负责维护引用一致性”。比如克隆一个含事件监听器或 dom 节点的对象,深克隆反而会让逻辑断裂——这时候该考虑的往往不是克隆,而是重构数据流或使用不可变更新模式。

text=ZqhQzanResources