繁体   English   中英

为什么改变一个数组会以某种方式改变另一个数组?

[英]Why does mutating one array somehow mutate another?

我创建了一个函数,旨在将多个多维数组合并在一起

输入“表”当前是包含在对象中的 2 个数组,该函数旨在每次运行命令时运行(我知道效率不高,但它适用于需要这样做的高中项目)

打印输入看起来像:

[ [ [ 'a', 1 ], [ 'b', 1 ] ], [ [ 'a', 1 ] ] ]

每次运行该函数时,都希望结果表看起来像这样:

[ [ 'a', 2 ], [ 'b', 1 ] ]

它不是增加 'tempTable[u][1]' 而是增加连接到输入表 [0] 的数组。

打印原始数组 [ [ 'a', 1 ], [ 'b', 1 ] ] 现在每次运行代码时都会显示 'a' 递增 1。

我不知道为什么它每次都增加原始数组而不是'tempArray',有人能向我解释为什么它增加原始表吗?

PS 这是这个函数的错误,如果我注释掉应该将'tempTable' 增加 1 的行,原始表不会改变。

 function combineTable(table) { var tempTable = table[0]; for (var i = 1; i < table.length; i++) { //each table for (var u = 0; u < tempTable.length; u++) { //temptable values for (var y = 0; y < table[i].length; y++) { //current table values if (tempTable[u][0] === (table[i])[y][0]) { tempTable[u][1] += (table[i])[y][1]; } else { console.log("Not contained"); } } } } } combineTable([ [ ['a', 1], ['b', 1] ], [ ['a', 1] ] ])

您需要为每个嵌套数组使用Array.prototype.slice()方法。

所以代替var tempTable = table[0]; ,你需要使用:

var tempTable = table[0].map(arr => arr.slice());

对于多维数组,您不能只说thing = arr[0] ,因为它只返回对值的引用,而不是复制的值。

 function combineTable(table) { var tempTable = table[0].map(arr => arr.slice()); // This is the line changed for (var i = 1; i < table.length; i++) { //each table for (var u = 0; u < tempTable.length; u++) { //temptable values for (var y = 0; y < table[i].length; y++) { //current table values if (tempTable[u][0] === (table[i])[y][0]) { tempTable[u][1] += (table[i])[y][1]; } else { console.log("Not contained"); } } } } // Adding console logging for demo console.log(table); console.log(tempTable); } combineTable([ [ ['a', 1], ['b', 1] ], [ ['a', 1] ] ])

注意:我写这个答案是因为我认为接受的答案没有清楚地回答你为什么修改一个数组会改变另一个的问题。

如果数组 A 和 B 是对同一数组的引用,则修改数组 A 也会修改数组 B。

const arrayA = [1]
const arrayB = arrayA;
arrayB[0] = 2;
console.log(arrayA, arrayB); // -> [2]   [2]

JavaScript 使用对象共享策略调用,这适用于数组,因为在 JavaScript 中,数组是一种对象。 如何在改变对象的同时避免副作用(例如改变其他对象)取决于数组中的数据类型。

因为 JavaScript 对基元使用按值传递,所以我们可以执行以下操作:

const array2D = [[1]];
const array1D = [ array2D[0][0] ];
array1D[0] = 2;
console.log(array2D, array1D); // -> [[1]]   [2]

但是,如果数组包含其他数组,则会重现我们的问题。

const array3D = [[[1]]];
const array2D = [ array3D[0][0] ];
array2D[0][0] = 2;
console.log(array3D, array2D) // -> [[[2]]]   [[2]]

本质上,如果您要改变对象的属性,请注意对该对象存在哪些引用。 如果我在编写 JavaScript 时考虑到这一点,那么我发现我不会经常遇到与此相关的问题。

如果您处于严重绑定中,您可以深度克隆一个对象以生成一个没有任何引用的新对象。 这有一些问题,这里有一个答案,显示了如何构建深度克隆函数以及它的问题:如何在 javascript 中进行深度克隆

并且 lodash 为它提供了一个实用程序_.cloneDeep()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM