关于javascript:为什么我不能在JS中复制这个2d数组?

Why can't I make a copy of this 2d array in JS? How can I make a copy?

我正在实施一个约翰·康威的人生游戏,但我遇到了一个奇怪的问题。如果代码给我带来麻烦,这里有一个简短的版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let lifeMap = [
  [true, false, false],
  [false, false, false],
  [false, false, false]
];
let oldLifeMap = lifeMap.slice();
for (let row = 0; row < lifeMap.length; row++) {
  for (let val = 0; val < lifeMap[row].length; val++) {
    let bool = lifeMap[row][val];
    let newBool = false; // here is where I would determine if cell is alive/dead
    lifeMap[row][val] = newBool;
    if (row === 0 && val === 0) console.log("at (0,0)", oldLifeMap[0][0]);
  }
}

为了响应此代码,javascript将打印at (0,0) false。我需要它在下一代开始之前一直留在江户。

我原以为做let oldLifeMap = lifeMap.slice()可以解决问题,但事实并非如此,我也不知道为什么。(它不应该复制二维数组而不创建对它的第二个引用吗?)

不管怎样,这里发生了什么,我如何成功地在这里复制了一份实际的lifeMap


对于N维数组来说,@redu's答案的帽子提示是很好的,但是对于二维数组来说,这是不必要的。为了深入克隆特定的二维阵列,您需要做的就是:

1
let oldLifeMap = lifeMap.map(inner => inner.slice())

这将使用不带参数的.slice()创建每个内部数组的副本,并将其存储到使用.map()创建的外部数组的副本中。


您可以如下克隆一个ND(深度嵌套)数组;

1
2
3
Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};

或者,如果您不想修改Array.prototype,您可以像这样简单地重构上述代码;

1
2
3
function cloneArray(a){
  return a.map(e => Array.isArray(e) ? cloneArray(e) : e);
};