ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

使用结构化克隆在 JavaScript 中进行深度复制

2022-01-12 21:03:40  阅读:176  来源: 互联网

标签:myOriginal 结构化 副本 克隆 JavaScript JSON 拷贝


在很长一段时间内,您不得不求助于变通方法和库来创建 JavaScript 值的深层副本。现在js提供 「structuredClone()」 一个用于深度复制的内置函数。

浏览器支持:

浅拷贝

在 JavaScript 中复制一个值几乎是浅拷贝,而不是深拷贝。这意味着对深度嵌套值的更改将在副本和原始值中可见。 使用对象扩展运算符 在 JavaScript 中创建浅拷贝的一种方法

const myOriginal = {
  someProp: "with a string value",
  anotherProp: {
    withAnotherProp: 1,
    andAnotherProp: true
  }
};

const myShallowCopy = {...myOriginal};

直接在浅副本上添加或更改属性只会影响副本,而不影响原始值:

myShallowCopy.aNewProp = "a new value";
console.log(myOriginal.aNewProp)
// ^ logs `undefined`

然而,添加或更改嵌套很深的属性会影响原始值和拷贝值:

myShallowCopy.anotherProp.aNewProp = "a new value";
console.log(myOriginal.anotherProp.aNewProp) 
// ^ logs `a new value`

对象扩展运算符遍历了myOriginal所有可枚举的属性。它使用属性名称和值,并将它们一一分配给一个新创建的空对象。因此,生成的对象在形状上是相同的,但具有自己的属性和值列表的副本。这些值也会被复制,但是 JavaScript 值处理所谓的基本类型的方式与处理非基本类型的方式不同。
非基本类型作为引用处理,这意味着复制值的行为实际上只是复制对同一底层对象的引用,从而导致浅复制行为。

深拷贝

与浅拷贝相反的是深拷贝。深拷贝算法也一个一个地拷贝一个对象的属性,但是当它找到对另一个对象的引用时递归地调用自己,同时创建该对象的副本。这对于确保两段代码不会意外共享一个对象并在不知不觉中操纵彼此的状态非常重要。
在 JavaScript 中创建值的深层副本过去没有简单或好的方法。很多人依赖第三方库,比如Lodash 的cloneDeep()函数。可以说,这个问题最常见的解决方案是基于 JSON 的 hack:

const myDeepCopy = JSON.parse(JSON.stringify(myOriginal));

事实上,这是一个非常流行的解决方法,V8 积极优化 JSON.parse(),特别是上面的模式,以使其尽可能快。虽然速度很快,但它也有一些缺点:

  • 递归数据结构:JSON.stringify()当你序列化一个递归数据结构时会报错。在使用链表或树时,这很容易发生。
  • 内置类型:JSON.stringify()如果值包含其他JS关键字,例如Map,Set,Date,RegExp或ArrayBuffer,也会报错。
  • Functions:JSON.stringify()有可能会丢掉函数。

结构化克隆

浏览器已经需要在几个地方创建 JavaScript 值的深层副本的能力:在 IndexedDB 中存储 JS 值需要某种形式的序列化,以便可以将其存储在磁盘上,然后反序列化以恢复 JS 值。类似地,向 WebWorker 发送消息postMessage()需要将 JS 值从一个 JS 领域传输到另一个领域。
HTML 规范进行了修改,以公开一个名为的函数structuredClone(),该函数完全运行该算法,作为开发人员轻松创建 JavaScript 值的深层副本的一种手段。

const myDeepCopy = structuredClone(myOriginal);

特点和限制

结构化克隆解决了该JSON.stringify()技术的许多(尽管不是全部)缺点。结构化克隆可以处理循环数据结构,支持许多内置数据类型,并且通常更健壮且通常更快。
但是,它仍然有一些限制可能会让您措手不及:

  • Prototypes:如果structuredClone()与类实例一起使用,您将获得一个普通对象作为返回值,因为结构化克隆会丢弃对象的原型链。
  • 函数:同样不支持函数。
  • Non-cloneables:一些值不是结构化可克隆的,最值得注意的是Error和 DOM 节点。它会导致structuredClone()抛出异常。

如果这些限制中的任何一个对您的用例造成破坏,像 Lodash 这样的库仍然提供其他深度克隆算法的自定义实现,这些算法可能适合您的用例,也可能不适合您的用例。

标签:myOriginal,结构化,副本,克隆,JavaScript,JSON,拷贝
来源: https://www.cnblogs.com/xiyangbaixue/p/15795263.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有