深拷贝一般都需要我们自己写代码来实现,比如通过递归、JSON的stringify()和parse()、Object.assign()等,现在提出了structuredClone方法,它属于浏览器原生方式,直接用于对象的的深拷贝(deep clone)。
structuredClone api 目前已经成为了一个 html 规范中的标准提案,用它可以轻松实现一个深拷贝,并且也默认解决了循环引用等问题、支持了很多默认的数据类型。
并且,相比 JSON.parse() ,structuredClone API 的性能更好,特别是在处理一些更大复杂的对象的时候,所以我们可以用它来作为代码里深拷贝的默认方法啦,为了兼容性考虑,可以用 JSON.stringify 或者其他工具函数作为备用
不过,这个 API 也并不完美,它也有些缺点:
原型:无法拷贝对象的原型链。
函数:无法拷贝函数。
不可克隆:并没有支持所有类型的拷贝,比如 Error。
当然,大部分实际的需求场景中,我们没必要拷贝这些东西,估计这些也就只能出现在面试题里面了。
structuredClone(value, { transfer })
value:要克隆的对象。
transfer:值为数组,其数组value将被移动而不是克隆到返回的对象中(选填)。
此函数可用于深度复制 JavaScript 值。它还支持循环引用,如下所示:
// Create an object with a value and a circular reference to itself.
const original = { name: "MDN" };
original.itself = original;
// Clone it
const clone = structuredClone(original);
console.assert(clone !== original); // the objects are not the same (not same identity)
console.assert(clone.name === "MDN"); // they do have the same values
console.assert(clone.itself === clone); // and the circular reference is preserved
transfer参数
以下代码显示了如何克隆一个数组并将其底层资源转移到新对象。返回时,原件uInt8Array.buffer将被清除。
var uInt8Array = new Uint8Array(1024 * 1024 * 16); // 16MB
for (var i = 0; i < uInt8Array.length; ++i) {
uInt8Array[i] = i;
}
const transferred = structuredClone(uInt8Array, { transfer: [uInt8Array.buffer] }).
console.log(uInt8Array.byteLength); // 0
您可以克隆任意数量的对象并传输这些对象的任何子集。例如,下面的代码arrayBuffer1将从传入的值传输,但不是arrayBuffer2.
const transferred = structuredClone(
{ x: { y: { z: arrayBuffer1, w: arrayBuffer2 } } },
{ transfer: [arrayBuffer1] });
目前,主流浏览器Safari已经在其94稳定版本支持了,Chrome和Safari将在最新版支持该方法,另外Node 17 和 Deno 1.14 也已经实现了这个 API,未来一定会成为一个被广泛使用的API的。
javascript的深拷贝和浅拷贝主要是针对像Object, Array这样的复杂对象的,简单理解为浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。
JSON.parse(),JSON.stringify()实现对对象的深拷贝以及兼容性问题,根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系。
克隆JavaScript对象,首页想到的是obj = eval(uneval(obj)),但这是非标准的,推荐使用jquery提供的jQuery.extend方法,因为它包含了一些额外的类型验证逻辑,并且不会复制未定义的属性等。
在JS中,一般的=号传递的都是对象/数组的引用,并没有真正地拷贝一个对象,那如何进行对象的深度拷贝呢?对象的深拷贝与浅拷贝的区别如下:浅拷贝:仅仅复制对象的引用,而不是对象本身;深拷贝:把复制的对象所引用的全部对象都复制一遍。
可以看出来,改变原数组arr,并没有对新数组copyArr产生影响;改变新数组copyArr也没有对原数组arr产生影响;同样:改变原数组arr,并没有对新数组copyArr产生影响;改变新数组copyArr也没有对原数组arr产生影响;
记录一个做leetcode看答案学到的小知识。。。浅拷贝实现一些特殊的功能的一些应用场景,比如:我们有一个需求如下
我们常常会用到拷贝对象的功能,而拷贝有浅拷贝和深拷贝2种。这篇文章会着重讲2个方面:1: 浅拷贝和深拷贝的区别2: 浅拷贝和深拷贝的具体实现,拷贝我们常常用在把A对象的属性copy到B对象,这样B对象就拥有了A对象的属性。
了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题
JavaScript中有两种数据类型,基本数据类型如undefined、null、boolean、number、string,另一类是Object。简单数据类型只存储在内存中的栈区,复制的时候是值传递给新的索引。而复杂数据类型由栈区和堆区共同储存
数组拷贝经常被误解,但这并不是因为拷贝过程本身,而是因为缺乏对 JS 如何处理数组及其元素的理解。JS 中的数组是可变的,这说明在创建数组之后还可以修改数组的内容。这意味着要拷贝一个数组,咱们不能简单地将旧数组分配给一个新变量
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!