JavaScript数组的浅拷贝和深拷贝有什么区别?

19
根据MDN文档,调用 array.slice()将创建一个数组的浅拷贝。 请参阅此MDN链接slice()
然而,如果我在控制台中运行以下简单测试:
var test = [[1,2,3],7,8,9];
var shallow_copy = test.slice();

并且检查shallow_copy,我可以看到整个二维数组似乎被复制了。

浅拷贝和深拷贝有什么区别?如果让我猜的话,我会称之为深拷贝。


这意味着 test[0] === shallow_copy[0],它们引用同一个数组对象。 - Bergi
我发现在JavaScript文档中使用“浅拷贝”和“深拷贝”这两个词完全令人困惑,因为已经明确说明对象永远不会被复制。当它明确标注为“浅拷贝”时,我会期望所有元素都是对同一事物的引用(包括非对象,如数字),但实际上只适用于已经声明不会被复制的对象。 - pishpish
2个回答

26

要看到区别,请尝试:

shallow_copy[0][2] = 4;
console.dir(test);

您会发现test已经被修改了!这是因为尽管您可能已经将值复制到新数组中,但嵌套的数组仍然是同一个数组。

深拷贝将递归执行浅拷贝,直到所有内容都是原始内容的新副本。


感谢您清晰的解释。我已经寻找相同的内容很长时间了。 - Shaik Md N Rasool

2

基本上你只是获取了对原始变量/数组的引用。更改引用也会更改原始数组。您需要循环遍历原始数组的值并形成副本。

考虑以下示例:

var orig = {  a: 'A', b: 'B', c: 'C' };

假设您想创建一个副本,以便即使更改了原始值,也可以随时返回到原始状态。
我可以这样做:
var dup = orig; //Shallow copy!

如果我们改变一个值:
dup.a = 'Apple';

这个语句还会改变orig中的a,因为我们进行了浅复制,或者说是对变量orig的引用。这意味着您也失去了原始数据。
但是,通过使用原始变量orig的属性创建全新的变量,您可以创建深层复制。
var dup = { a: orig.a, b: orig.b, c: orig.c }; //Deep copy!

现在如果您更改dup.a,它只会影响dup而不会影响orig

9
那不是浅拷贝,其实根本没有进行拷贝操作。 - Niet the Dark Absol
我可能错了,请随意纠正!这是我从一个老经验中学到的。 - Rutwick Gangurde
3
这只是传递引用,不是浅拷贝或深拷贝。请参考https://dev59.com/r3VC5IYBdhLWcg3wykUt中的最佳答案,了解浅拷贝和深拷贝之间的区别。此外,在你的例子中你所说的“深拷贝”实际上是浅拷贝。 - elachell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接