【问题标题】:In JS, why does the slice() documentation say it is a shallow copy when it looks like a deep copy?在 JS 中,为什么 slice() 文档看起来像深拷贝时却说它是浅拷贝?
【发布时间】:2018-01-29 15:43:25
【问题描述】:

根据 JavaScript 中 Array.prototype.slice() 的文档,slice() 方法将数组的一部分的浅表副本返回到新数组中。据我了解,浅拷贝只会复制数组中的顶级元素,不会复制嵌套元素。但是,当我在浏览器控制台中运行测试时,看起来slice() 方法实际上是在复制嵌套元素(深度复制)。

我在哪里误解了深拷贝的概念?请帮我澄清一下,因为它与我的确切示例有关。

var array = [1,2,[3,4,[5,6]]];
var array2 = array.slice();

【问题讨论】:

标签: javascript arrays deep-copy


【解决方案1】:

它正在做一个浅拷贝。但是该浅拷贝中的值指向原始数组/对象,因为它们是对象引用。

假设我们有:

var orig = [ [1] ];

在记忆中我们有:

+−−−−−−−−−−−−−−+ [orig:Ref22157]---->| (数组) | +−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ | 0: Ref84572 |−−−−−−−−>| (数组) | +−−−−−−−−−−−−−−+ +−−−−−−−−−−−−−−+ | 0:1 | +−−−−−−−−−−−−−−+

现在我们做:

var copy = orig.slice();

并且拥有:

+−−−−−−−−−−−−−−+ [orig:Ref22157]---->| (数组) | +−−−−−−−−−−−−−−+ | 0: Ref84572 |−−−+ +−−−−−−−−−−−−−−+ | | | +−−−−−−−−−−−−−−+ +−−−>| (数组) | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ [复制:Ref54682]---->| (数组) | | | 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]),我们都会看到该修改。

【讨论】:

    【解决方案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]
    

    【讨论】:

      【解决方案3】:

      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]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-12
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        • 2015-01-13
        • 2011-09-05
        • 1970-01-01
        • 2010-09-16
        相关资源
        最近更新 更多