请检查以下内容...
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
请帮助我理解这一点,以避免出现这种情况。
答案 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)
时,它会创建一个“浅表副本”-一个新数组,但原始数组具有相同的内容。这意味着arr
和otherArr
是两个单独的数组,但是指向相同的内容。 arr[0]
是与otherArr[0]
相同的对象,而arr[1]
是与otherArr[1]
相同的对象
arr [ 0 , 1 ]
| |
v v
['test', 1], ['test', 5]
^ ^
| |
otherArr [ 0 , 1 ]
现在您的问题是
当我评估arr === otherArr时,结果为FALSE。
如上所述,arr
和otherArr
是两个不同的数组,导致===
失败。对于非基元,===
检查身份(即,是否是同一对象?)。另外请注意,===
和==
并不是结构检查(即它们看起来一样吗?)。
当我执行以下操作时,尝试更改第一个数组值:
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 ]