根据JavaScript中Array.prototype.slice()
的文档,slice()
方法将数组的一部分的浅表副本返回到新数组中。据我所知,浅拷贝只会复制数组中的顶级元素,不会复制嵌套元素。但是,当我在浏览器控制台中运行测试时,确实看起来slice()
方法实际上是复制嵌套元素(深度复制)。
我在哪里误解了深层复制的概念?请帮我澄清,因为它与我的确切例子有关。
var array = [1,2,[3,4,[5,6]]];
var array2 = array.slice();
答案 0 :(得分:5)
它正在做一个浅薄的副本。但是浅拷贝中的值指向原始数组/对象,因为它们是对象引用。
所以,让我们说:
var orig = [ [1] ];
在记忆中我们有:
+−−−−−−−−−−−−−+ [orig:Ref22157]−−−−>| (array) | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | 0: Ref84572 |−−−−−−−>| (array) | +−−−−−−−−−−−−−+ +−−−−−−−−−−−−−+ | 0: 1 | +−−−−−−−−−−−−−+
现在我们做:
var copy = orig.slice();
并且:
+−−−−−−−−−−−−−+ [orig:Ref22157]−−−−>| (array) | +−−−−−−−−−−−−−+ | 0: Ref84572 |−−−+ +−−−−−−−−−−−−−+ | | | +−−−−−−−−−−−−−+ +−−−>| (array) | +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−+ [copy:Ref54682]−−−−>| (array) | | | 0: 1 | +−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−+ | 0: Ref84572 |−−−+ +−−−−−−−−−−−−−+
请注意对嵌套数组的引用(此处在概念上显示为" Ref84572"但我们从未看到对象引用的实际值)已被复制,但仍引用相同的嵌套数组。
这里证明它很浅:
var orig = [ [1] ];
var copy = orig.slice();
console.log("orig[0][0] = " + orig[0][0]);
console.log("copy[0][0] = " + copy[0][0]);
console.log("Setting copy[0][0] to 2");
copy[0][0] = 2;
console.log("orig[0][0] = " + orig[0][0]);
console.log("copy[0][0] = " + copy[0][0]);

请注意,当我们修改嵌套数组的状态时,无论我们采用哪条路线(orig[0][0]
或copy[0][0]
),我们都会看到该修改。
答案 1 :(得分:2)
在这种情况下,浅拷贝意味着嵌套对象将指向原始值。因此,通过修改切片数组中的嵌套对象,您将改变原始。
最好看一下这个例子:
var originalArray = [1, [2, 3], 4];
var slicedArray = originalArray.slice();
var nestedArray = slicedArray[1]; // [2, 3]
nestedArray.push("oh no, I mutated the original array!");
console.log(originalArray); // [1, [2, 3, "oh no, I mutated the original array!"], 4]
答案 2 :(得分:1)
slice
是浅层副本,不是因为嵌套值被忽略,而是因为它们包含对原始数组的引用,因此仍然是链接的。例如:
let arr = [1, [2]]
let shallowCopy = arr.slice(0, arr.length);
shallowCopy[1][0] = "foobar";
// will print "foobar", because the nested array is just a reference
console.log(arr[1][0]);