在 JS 中,为什么 slice() 文档说它是浅拷贝,而它看起来像深拷贝?
In JS, why does the slice() documentation say it is a shallow copy when it looks like a deep copy?
根据 JavaScript 中 Array.prototype.slice()
的文档,slice()
方法 returns 将数组的一部分浅拷贝到新数组中。据我了解,浅拷贝只会复制数组中的顶级元素,而不会复制嵌套元素。但是,当我 运行 在我的浏览器控制台中进行测试时,看起来 slice()
方法确实在复制嵌套元素(深度复制)。
我哪里误解了深拷贝的概念?请帮我澄清一下,因为它与我的确切示例有关。
var array = [1,2,[3,4,[5,6]]];
var array2 = array.slice();
它正在做一个浅拷贝。但该浅拷贝中的值指向原始 arrays/objects,因为它们是对象引用。
假设我们有:
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]
),我们都会看到该修改。
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]);
在这种情况下,浅拷贝意味着嵌套对象将指向原始值。因此,通过修改切片数组中的嵌套对象,您将改变原始对象。
最好看例子:
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]
根据 JavaScript 中 Array.prototype.slice()
的文档,slice()
方法 returns 将数组的一部分浅拷贝到新数组中。据我了解,浅拷贝只会复制数组中的顶级元素,而不会复制嵌套元素。但是,当我 运行 在我的浏览器控制台中进行测试时,看起来 slice()
方法确实在复制嵌套元素(深度复制)。
我哪里误解了深拷贝的概念?请帮我澄清一下,因为它与我的确切示例有关。
var array = [1,2,[3,4,[5,6]]];
var array2 = array.slice();
它正在做一个浅拷贝。但该浅拷贝中的值指向原始 arrays/objects,因为它们是对象引用。
假设我们有:
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]
),我们都会看到该修改。
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]);
在这种情况下,浅拷贝意味着嵌套对象将指向原始值。因此,通过修改切片数组中的嵌套对象,您将改变原始对象。
最好看例子:
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]