当前位置: 首页 > 新闻动态 > 网络资讯

javascript如何深度克隆对象_有哪些注意事项【教程】

作者:紅蓮之龍 浏览: 发布日期:2026-01-27
[导读]:JSON.stringify+JSON.parse不能直接用于深克隆,仅适用于纯数据对象;structuredClone在支持环境下更优但不支持function等类型;手写需处理循环引用、原型链等边界;lodash.cloneDeep覆盖广但有局限。
JSON.stringify + JSON.parse 不能直接用于深克隆,仅适用于纯数据对象;structuredClone 在支持环境下更优但不支持 function 等类型;手写需处理循环引用、原型链等边界;lodash.cloneDeep 覆盖广但有局限。

JSON.stringify + JSON.parse 能不能直接用

不能,这是最常踩的坑。它只适用于纯数据对象(plain object),一旦遇到 DateRegExpundefinedfunctionSymbolMapSet 或循环引用,就会出错或丢数据。

比如:JSON.stringify({ d: new Date() }) 得到 {"d":"2025-01-01T00:00:00.000Z"} —— Date 变成了字符串,类型丢失;JSON.stringify({ f: () => {} }) 直接忽略 f 字段。

适用场景仅限于:你 100% 确认对象里只有字符串、数字、布尔、null、数组和嵌套的普通对象。

structuredClone 是不是万能解

在支持它的环境里(Chrome 98+、Firefox 94+、Node.js 17.0+),structuredClone 是目前最接近“开箱即用”的方案,能正确处理 DateMapSetArrayBufferTypedArrayBigInt 和循环引用。

但它不支持:functionundefinedSymbolPromiseError 对象,遇到会直接抛错:DataCloneError: function is not supported

使用前务必检查运行时支持:

if (typeof structuredClone === 'function') {
  try {
    const clone = structuredClone(obj);
  } catch (e) {
    console.error('克隆失败:', e.message);
  }
} else {
  // 降级处理
}

手写递归克隆要注意哪些边界

手动实现时,核心是识别类型并分发处理,但容易漏掉几个关键点:

  • obj === null 必须先判断,否则 typeof null"object",会误入对象分支
  • Array.isArray(obj)obj instanceof Array 更可靠,尤其跨 iframe 时
  • 需要缓存已遍历的对象(用 WeakMap),否则遇到循环引用会栈溢出
  • Object.getPrototypeOf(obj) 要保留,否则克隆后的对象原型链断裂(比如 new Date() 克隆后变 plain object)

示例片段(简化版):

function deepClone(obj, map = new WeakMap()) {
  if (obj === null || typeof obj !

== 'object') return obj; if (map.has(obj)) return map.get(obj); const cloned = Array.isArray(obj) ? [] : Object.create(Object.getPrototypeOf(obj)); map.set(obj, cloned); for (const key in obj) { if (Object.hasOwn(obj, key)) { cloned[key] = deepClone(obj[key], map); } } return cloned; }

lodash.cloneDeep 和其他库的实际差异

lodash.cloneDeep 在工程中仍是稳妥选择,它覆盖了绝大多数边缘类型:支持 MapSetRegExpDateUint8Array,甚至能克隆自定义类的实例(只要构造函数可访问且无副作用)。

但它不处理:function(原样引用)、Symbol 键(ES2015+ 的 symbol 属性默认被忽略)、prototype 上的属性(只克隆自有属性)。

注意两个常见陷阱:

  • 如果对象里有 document 节点或 window 引用,cloneDeep 会静默失败或返回空对象
  • 性能敏感场景(如每帧克隆大型数据结构),cloneDeep 的类型检测开销比 structuredClone 高不少

真正难处理的永远是“混合状态”:比如一个对象既有 Map 又有 canvas.getContext('2d'),这种没法靠通用方案解决,得按业务定制序列化逻辑。

免责声明:转载请注明出处:http://shjed.com/news/728527.html

扫一扫高效沟通

多一份参考总有益处

免费领取网站策划SEO优化策划方案

请填写下方表单,我们会尽快与您联系
感谢您的咨询,我们会尽快给您回复!