js - 将数组 A 推入多维数组 B 时,它会覆盖 A 上已有的数组

js - When pushing an array A into a multidimensional array B, it is overwriting the previous array already on A

这是来自浏览器控制台的示例

a=[[1,2,3],[3,2,1]]
b=[]
b.push(a)
a[0][0]=9
b.push(a)

在那种情况下,我希望 b 是

[[[1,2,3],[3,2,1]],[[9,2,3],[3,2,1]]]

但会是

[[[9,2,3],[3,2,1]],[[9,2,3],[3,2,1]]]

我附上了一张屏幕截图,以便更好地在浏览器中显示结果: browsers console with the same code as above and output

关于为什么会发生这种情况以及如何达到我的预期结果有什么想法吗?

在 JavaScript 中,对象通过引用传递,这意味着它的“副本”不是副本。它们指向 RAM 中的相同地址,因此改变一个引用会改变它们。

要应用于这种情况,如果您还不知道,数组是特殊类型的对象。为了证明这一点,您可以在浏览器控制台中 运行 typeof [] 。这意味着数组会继承“pass-by-reference”行为,这意味着如果您执行 let c = a,那么 运行 c[0] = 1a 也会更改,反之亦然。

要解决此问题,您可以使用 Array.prototype.slice:

const a = [[1, 2, 3], [3, 2, 1]];
const b = [];

Array.prototype.pushWithoutReference = function(add) {
  for(let i = 0; i < add.length; i++) {
    this[this.length] = add[i].slice(0);
  }
}

b.pushWithoutReference(a);
a[0][0] = 9;
b.pushWithoutReference(a);

对于语言本身,没有多维数组 - 数组中还有另一个数组。是否包含数组、普通对象、函数或原语并不重要。对于基元,它们的值将被复制。否则,将复制对对象的引用。

您可以在 mapspread operator(...).

的帮助下,通过推送数组 a 的内部数组的副本来完成此操作

var a=[[1,2,3],[3,2,1]];
var b=[];
b.push(a.map(x=>[...x]));
a[0][0]=9;
b.push(a);
console.log(b);

好的,基于这里的所有评论,特别是@code 的评论,还有另一个 post (How do I pass the value instead of the reference of an array?) 我能够通过使用这个获得结果:

b.push([]); 
for(line of a){ 
    b[b.length-1].push(a.slice(0)); 
}

编辑

A​​bhijeet 的建议也完美无缺:

b.push(a.map(x=>[...x]));