为什么这两个 javascript 二维数组的行为不同?

IT技术 javascript arrays multidimensional-array
2021-03-03 09:26:45

在我的函数中,我定义了两个数组,第一个 ( array1 ) 具有预先初始化的长度。我添加了第二个数组 ( array2 ) 只是为了测试,因为我认为第一个的行为很奇怪。

我的代码:

function test(n = 3) {
  array1 = new Array(n).fill(new Array(n));
  array2 = [
    [undefined, undefined, undefined],
    [undefined, undefined, undefined],
    [undefined, undefined, undefined]
  ];

  document.getElementById("output").innerHTML = JSON.stringify(array1) + " (array 1) <br/>" + JSON.stringify(array2) + " (array 2)<br/><br/><hr/>";


  for (i = 0; i < n; i++) {
    array1[i][0] = i;
    array2[i][0] = i;
  }

  document.getElementById("output").innerHTML += JSON.stringify(array1) + " (array 1) <br/>" + JSON.stringify(array2) + " (array 2)<br/><br/><hr/>";

}
<button onclick="test();">Press to test</button>

<br/><br/>
<div id="output"></div>

for循环中,我尝试更改第二个维度的第一个值。它应该输出[[0, undefined, undefined], [1, undefined, undefined], [2, undefined, undefined]],就像第二个数组一样。

我的问题是:为什么会发生这种情况?而且,我怎样才能制作一个在两个维度上都具有长度n的预初始化数组,它的行为类似于第二个数组?

2个回答

那是因为如果array1它包含三个数组,但它们三个都指向相同的引用变量,该变量在new Array(n)执行评估

var array1 = new Array(n).fill(new Array(n));

因此,当for循环运行时,array1它正在设置相同数组引用的值,而在array2这三个数组的情况下是不同的引用变量。

这是您的代码段的略微修改版本。array1's 元素的值被更改时,请注意控制台中的条目如果array1三个子数组都发生了变化,而在array2循环下使用索引引用的数组i是唯一发生变化的。

function test(n = 3) {
  array1 = new Array(n).fill(new Array(n));
  array2 = [
    [undefined, undefined, undefined],
    [undefined, undefined, undefined],
    [undefined, undefined, undefined]
  ];

  document.getElementById("output").innerHTML = JSON.stringify(array1) + " (array 1) <br/>" + JSON.stringify(array2) + " (array 2)<br/><br/><i>The commas with nothing in between mean undefined.</i><hr/>";


  for (i = 0; i < n; i++) {
    array1[i][0] = i;
    array2[i][0] = i;
    console.log("Array 1: " + JSON.stringify(array1));
    console.log("Array 2: " + JSON.stringify(array2));
  }

  document.getElementById("output").innerHTML += JSON.stringify(array1) + " (array 1) <br/>" + JSON.stringify(array2) + " (array 2)<br/><br/><i>The commas with nothing in between mean undefined.</i><hr/>";

}
<button onclick="test();">Press to test</button>

<br/><br/>
<div id="output"></div>

不错的答案!但是,我如何定义array1以便预初始化?第二个数组适用于 n = 3 的这种情况,但是,例如,如果 n = 5 呢?
2021-05-12 09:26:45
我可能会做一些像这样,但龚如心在肖尔茨她的回答解释了不同的方法为好。
2021-05-17 09:26:45
对于这样一个简单的任务,创建一个完整的 for 循环似乎有点太多代码:) 所以我想我会使用 Nina 的答案。
2021-05-19 09:26:45

因为 Array.fill

fill()方法使用静态值填充数组从开始索引到结束索引的所有元素。

接受一个静态值并用它填充数组。因此,您会进入array1同一填充数组的每个元素

function test(n = 3) {
    var array1 = new Array(n).fill(new Array(n)),
        array2 = [[undefined, undefined, undefined], [undefined, undefined, undefined], [undefined, undefined, undefined]],
        i;

    for (i = 0; i < n; i++) {
        array1[i][0] = i;
        array2[i][0] = i;
    }

    document.getElementById("output").innerHTML = array1 + " (array 1) <br/>" + array2 + " (array 2)<br/><br/><i>The commas with nothing in between mean undefined.</i>";
    console.log(array1);
    console.log(array2);
}
<button onclick="test();">Press to test</button><br/><br/>
<div id="output"></div>

要获得独立的填充数组,您可以使用Array.from并映射具有映射值的新数组。

var array = Array.from({ length: 3 }, _ => Array.from({ length: 3 }, _ => 4));

array[0][0] = 0;
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }