获得鼎晖领投的2400万Pre-A轮融资后,他再次创办了一家名为“阅读伴侣”的企业,改变中国少儿英语教育
06-17
作者:Surma 原文链接:使用 StructuredClone 在 JavaScript 中进行深度复制 译者:Yodonicc JavaScript 现在配备了 StructuredClone(),这是一个用于深度复制的内置函数。很长一段时间以来,您必须求助于黑魔法和第三方库来创建 JavaScript 值的深层副本。
ECMAScript 现在提供 StructuredClone(),这是一个用于深度复制的内置函数。浏览器支持:Browser support.png MDN 官方声明,在撰写本文时,所有浏览器都已在其最新版本中实现了此 API,并且 Firefox 已在 Firefox 94 中将其发布到稳定版本。
另外,Node 17和Deno 1.14也实现了这个API。您现在就可以开始使用此功能,不会出现任何问题。
浅复制 在 JavaScript 中复制值几乎总是浅的,而不是深的。这意味着对深度嵌套值的更改将在副本和原始值中可见。
在 JavaScript 中使用对象扩展运算符 (...) 是创建浅拷贝的一种方法: 代码语言: javascript copy const myOriginal = { someProp: "has a string value". anotherProp: { withAnotherProp: 1, andAnotherProp: true }};const myShallowCopy = {...myOriginal};直接在浅副本上添加或更改属性只会影响副本,而不会影响原始副本。代码语言: javascript copy myShallowCopy.aNewProp = "a new value";console.log(myOriginal.aNewProp)// ^ logs `undefined` 但是,添加或更改深度嵌套属性将同时影响副本和原始属性。
代码语言: javascript copy myShallowCopy.anotherProp.aNewProp = "a new value";console.log(myOriginal.anotherProp.aNewProp) // ^ 在 myOriginal 中使用 Spread 运算符记录 `a new value` 表达式 {...myOriginal} 迭代(可枚举)属性。它获取属性名称和值并将它们一一分配给新创建的空对象。
因此,生成的对象在结构上是相同的,但具有自己的属性和值列表副本。值也会被复制,但所谓的原始值与非原始值的处理方式不同。
引用MDN:在JavaScript中,原始值(原始数据类型)是指不属于对象且没有方法的数据。有七种基本数据类型:字符串、数字、bigint、布尔值、未定义、符号和 null。
MDN - 原始非原始值被视为引用,这意味着复制值的行为实际上只是复制对同一底层对象的引用,从而导致浅复制行为。深复制 与浅复制相反的是深复制。
深拷贝算法也是逐一复制一个对象的属性,但是当它找到另一个对象的引用时,它会递归调用自身并创建该对象的副本。这对于确保两段代码不会意外共享对象并在不知不觉中操纵彼此的状态非常重要。
过去,没有简单或好的方法可以在 JavaScript 中创建值的深层副本。许多人依赖第三方库,例如 Lodash 的 cloneDeep() 函数。
可以说,这个问题最常见的解决方案是基于 JSON 的黑魔法: 代码语言: javascript copy const myDeepCopy = JSON.parse(JSON.stringify(myOriginal));事实上,这是一个非常流行的解决方法,V8 积极优化 JSON.parse(),尤其是上面的模式,使其尽可能快。虽然它速度很快,但它有一些缺点和绊脚石:递归数据结构。
当您给 JSON.stringify() 提供递归数据结构时,它会抛出(异常)。在处理链表或树时,很容易发生这种情况。
内置类型。如果 JSON.stringify() 包含其他 JS 内置类型,例如 Map、Set、Date、RegExp 或 ArrayBuffer,则会抛出(异常)。
功能。 JSON.stringify() 将默默地丢弃该函数。
结构化克隆 ECMAScript 已经要求能够在某些地方创建 JavaScript 值的深层副本。在 IndexedDB 中存储 JS 值需要某种形式的序列化,以便可以将其存储在磁盘上,并在稍后反序列化以恢复 JS 值。
同样,通过 postMessage() 向 WebWorker 发送消息需要将 JS 值从一个 JS 领域移动到另一个 JS 领域。用于此目的的算法称为“结构化克隆”,直到最近开发人员才可以直接使用。
现在情况已经改变了! HTML 规范已经过修订,公开了一个名为 StructuredClone() 的函数,该函数完全运行此算法,作为开发人员轻松创建 JavaScript 值的深层副本的一种方法。代码语言:javascript copy const myDeepCopy = StructuredClone(myOriginal);就是这样!这就是整个 API。
如果您想了解详细信息,请查看这篇 MDN 文章。功能和限制 结构化克隆解决了 JSON.stringify() 技术的许多(尽管不是全部)缺点。
结构化克隆可以处理循环数据结构,支持许多内置数据类型,通常更健壮,并且通常更快。然而,它仍然有一些可能让您措手不及的限制:原型。
如果对类的实例使用 StructuredClone(),您将得到一个普通对象作为返回值,因为结构化克隆会丢弃该对象的原型链。功能。
如果您的对象包含函数,它们将被默默丢弃。不可克隆的对象。
有些值在结构上是不可克隆的,尤其是 Error 和 DOM 节点。这将导致 StructuredClone() 被抛出。
如果这些限制对您的用例构成阻碍,Lodash 等库仍然提供其他深度克隆算法的自定义实现,这些算法可能适合也可能不适合您的用例。性能 虽然我没有进行新的微基准比较,但我在年初、在 StructuredClone() 曝光之前进行了一次比较。
当时,对于非常小的对象,JSON.parse() 是最快的选择。我预计这一点将保持不变。
对于较大的对象,依赖于结构化克隆的技术(显着)更快。考虑到新的 StructuredClone() 没有滥用其他 API 的开销,并且比 JSON.parse() 更强大,我建议您将其作为创建深拷贝的默认方法。
结论如果你需要在 JS 中创建一个值的深拷贝——也许是因为你使用的是不可变的数据结构,或者你想确保一个函数可以对一个对象进行操作而不影响原始对象——你不再需要寻找黑魔法或第三方库。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-17
06-21
06-06
06-18
06-18
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用