非等于数组同时更改值的javascript

时间:2018-08-29 20:40:42

标签: javascript arrays multidimensional-array

请检查以下内容...

var arr = [["test", 1], ["test", 3], ["test", 5]]
var otherArr = arr.slice(0) //should be a new array with a copy of arr

当我评估arr === otherArr时,结果为 FALSE

当我执行以下操作时,尝试更改第一个数组值:

otherArr[0][1] = otherArr[0][1] + 5;

它还会更改原始数组(arr)

arr[0][1] === otherArr[0][1]的值为 TRUE

arr === otherArr评估为 FALSE

请帮助我理解这一点,以避免出现这种情况。

4 个答案:

答案 0 :(得分:1)

  

当我评估arr === otherArr时,结果为 FALSE

因为切片不是同一数组。
它本质上是数组内容的副本。

  

当我执行以下操作时,尝试更改第一个数组值:

otherArr[0][1] = otherArr[0][1] + 5;
     

它还会更改原始数组(arr)

     

arr[0][1] === otherArr[0][1]的值为 TRUE

     

arr === otherArr评估为 FALSE

是,因为数组是对象而不是原始值。

您要将arr的所有内容复制到otherArr
但您不会为其引用的对象创建副本。

如果其中有简单的值,例如数字,字符串,布尔值甚至可能是正则表达式,则可以确保将其复制。

如果您访问一个子数组,那么如果您想要一个实际的副本,也需要先创建该子数组的一个切片。

因为arr只是指向数组。它不包含它们。它们是参考。


还请查看问题下方Calvin Nunes的评论:

您可以通过将数组先转换为json字符串,然后再转换为数组来创建深层副本:
otherArr = JSON.parse(JSON.stringify(arr))

请记住,这仅适用于简单的东西,但是如果您要复制包含自定义函数等的对象,则可以不用理会。
它们不会被添加到json表示中,并且会丢失。

json只是一种用于运输的格式。
如果将来遇到这种要求,您可能需要考虑重写代码。
这总是导致代码变慢。

您可能希望递归地复制数组。
就像..遍历数组一样,如果成员是array类型,也要遍历数组。

嗯..有各种各样的深层复制解决方案。您只需要使用Google即可。

答案 1 :(得分:1)

这是因为数组是与slice()

不同的对象
arr === otherArr // false (different objects)

但是存储在数组中的值是相同的对象

 arr[0][1] === otherArr[0][1] 

如果您不希望出现这种情况,则需要对数组进行deep copy而不是切片。

以下是有关与数组有关的deep copy的一些信息:https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm

答案 2 :(得分:1)

问题是

  

slice()方法返回副本[…]

您仅复制第一级,因此必须更深入地进行复制。您可以这样做:

    var arr = [["test", 1], ["test", 3], ["test", 5]]
    
    var otherArr = [...arr[0], ...arr[1], ...arr[2]]
    
    
    otherArr[0][1] = otherArr[0][1] + 5;
    
    console.log(arr)

JSON.parse(JSON.stringify(arr))方法通常是最好的解决方案。

答案 3 :(得分:1)

最好从视觉上解释。想象一下arr如下图。它实际上由3个数组组成,一个数组引用了另外两个数组:

arr [     0      ,      1      ]
          |             |
          v             v
      ['test', 1], ['test', 5]

当您完成otherArr.slice(0)时,它会创建一个“浅表副本”-一个新数组,但原始数组具有相同的内容。这意味着arrotherArr是两个单独的数组,但是指向相同的内容。 arr[0]是与otherArr[0]相同的对象,而arr[1]是与otherArr[1]相同的对象

arr      [     0      ,      1      ]
               |             |
               v             v
           ['test', 1], ['test', 5]
               ^             ^
               |             |
otherArr [     0      ,      1      ]

现在您的问题是

  

当我评估arr === otherArr时,结果为FALSE。

如上所述,arrotherArr是两个不同的数组,导致===失败。对于非基元,===检查身份(即,是否是同一对象?)。另外请注意,=====并不是结构检查(即它们看起来一样吗?)。

  

当我执行以下操作时,尝试更改第一个数组值:

otherArr[0][1] = otherArr[0][1] + 5;
     

它还会更改原始数组(arr)

arr[0][1] === otherArr[0][1] evaluates to TRUE

回到我们的图,您实际上正在做的是更改两个数组都引用的对象的内容(在这种情况下,现在是['test', 6])。

arr      [     0      ,      1      ]
               |             |
               v             v
           ['test', 6], ['test', 5]
               ^             ^
               |             |
otherArr [     0      ,      1      ]