JavaScript 深度克隆对象的现代方法:structuredClone

本文介绍了JavaScript中的structuredClone方法,一种深度复制复杂对象的新功能,它能递归复制对象和数组,支持多种类型,包括WebAPI,且在浏览器和Node.js中有良好兼容性。相比之下,传统方法如对象扩展运算符、JSON.parse与JSON.stringify存在局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在JavaScript中,深度复制复杂对象一直是一个常见的需求。传统的解决方案如对象扩展运算符、JSON.parse与JSON.stringify组合,以及第三方库(例如Lodash的_.cloneDeep)都存在局限性。而现在,JavaScript运行时内置了一个名为structuredClone的方法,它可以有效地解决这些问题。

structuredClone 的功能特性

  • 深度复制structuredClone能够递归地复制对象和数组,确保原始对象与其副本之间的引用独立。
const calendarEvent = {
  title: "Builder.io Conf",
  date: new Date(123),
  attendees: ["Steve"]
};

const copied = structuredClone(calendarEvent);
copied.attendees.push("Bob"); // 不会影响原对象
  • 广泛类型支持:不仅能复制常见JS类型(包括Date, Set, Map, Error, RegExp, ArrayBuffer等),还能处理Blob, File, ImageData等多种Web API类型,并且可以处理循环引用。

  • 无限层级嵌套:无论嵌套结构多么复杂,都能正确复制。

为什么不用其他方法?

对象扩展运算符 {…}

当需要浅层复制时,对象扩展运算符是很好的选择。

const simpleEvent = {
  title: "Builder.io Conf",
};

// 浅层复制,适用于无嵌套对象或数组的情况
const shallowCopy = {...simpleEvent};

然而,当面对包含嵌套对象或数组的对象时,它只会创建一层新的引用,扩展运算符无法完成深度复制:

const calendarEvent = {
  title: "Builder.io Conf",
  date: new Date(123),
  attendees: ["Steve"]
};

const shallowCopy = {...calendarEvent};

// 🚩 问题出现 - 修改副本同时也影响了原始对象
shallowCopy.attendees.push("Bob");

// 🚩 同样问题 - 更新副本的同时也更新了原始对象的时间
shallowCopy.date.setTime(456);

JSON.parse(JSON.stringify(x))

使用这种方法虽然性能不错,但它仅能处理基础对象、数组和原始类型。对于Date对象会转换为字符串表示,而对于Set、Map等类型则可能无法预期地转为空对象,甚至忽略undefined和函数等属性。此外,它不能处理循环引用并会抛出错误。

const calendarEvent = {
  title: "Builder.io Conf",
  date: new Date(123),
  attendees: ["Steve"]
};

// 使用JSON.stringify进行序列化,然后JSON.parse解析回对象
const problematicCopy = JSON.parse(JSON.stringify(calendarEvent));

// 输出结果:
// {
//   "title": "Builder.io Conf",
//   "date": "1970-01-01T00:00:00.123Z",
//   "attendees": ["Steve"]
// }

Lodash 的 _.cloneDeep 方法

Lodash的_.cloneDeep方法确实能够满足深度复制的需求,然而其大小约为17.4KB(minified)、5.3KB(gzipped)。考虑到浏览器已经内置了structuredClone方法,额外引入一个大型库显得没有必要。

structuredClone 不支持的内容

  • 函数:尝试复制函数会导致DataCloneError异常。

  • DOM节点:同样会引发DataCloneError异常。

  • 属性描述符、setter 和 getter:不会复制这些元数据属性。getter属性的值会被复制,但getter函数本身不会被复制。

  • 对象原型:不遍历或复制原型链,因此克隆后的对象不再属于原始构造函数的实例,尽管其属性会被复制。

支持的类型一览

structuredClone支持以下类型:

  • JS 内置类型:Array、ArrayBuffer、Boolean、DataView、Date、特定Error类型、Map、纯对象、原始类型(除symbol外)、RegExp、Set、TypedArray

  • 错误类型:Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError

  • Web/API 类型:AudioData、Blob、CryptoKey、DOMException、DOMMatrix、DOMMatrixReadOnly、DOMPoint、DomQuad、DomRect、File、FileList、FileSystemDirectoryHandle、FileSystemFileHandle、FileSystemHandle、ImageBitmap、ImageData、RTCCertificate、VideoFrame

浏览器兼容性

structuredClone已在所有主流浏览器及Node.js、Deno环境中得到支持。需要注意的是,在Web Worker中的支持相对有限。

参考链接:MDNDeep Cloning Objects in JavaScript, the Modern Way

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值