为什么输出这么奇怪! fill 方法实际上在做什么?
Expected output: [[0, 0, 0], [0, 5, 0], [0, 0, 0]]
Actual output: [[0, 5, 0], [0, 5, 0], [0, 5, 0]]
let matrix = new Array(3).fill(new Array(3).fill(0)); // creates a 2d Array and fills them with 0
matrix[1][1] = 5; // say
console.log(matrix);
您所看到的行为是由于
Array.fill()
如何处理对象(尤其是 JavaScript 中的数组)而导致的。让我们来分析一下发生了什么:
let matrix = new Array(3).fill(new Array(3).fill(0));
在这一行中,
new Array(3)
创建了一个包含三个空槽的数组,然后使用fill(new Array(3).fill(0))
进行填充。
但是,出现问题是因为
new Array(3).fill(0)
创建了数组 [0, 0, 0]
的单个实例,并且该单个实例用于填充外部数组的所有三个槽。因此,实际上,您的 matrix
数组最终看起来像这样:
matrix = [
[0, 0, 0], // All three inner arrays point to the same array object in memory
[0, 0, 0],
[0, 0, 0]
];
当您修改
matrix[1][1] = 5;
时,您正在修改由外部数组的所有三个槽引用的同一内部数组。因此,所有行都会反映此更改,从而产生输出:
[[0, 5, 0], [0, 5, 0], [0, 5, 0]]
要解决此问题并创建一个适当的二维数组,其中每行都是独立的,您应该单独初始化每一行,如下所示:
let matrix = new Array(3);
for (let i = 0; i < matrix.length; i++) {
matrix[i] = new Array(3).fill(0);
}
这样,每一行(
matrix[i]
)都会获得自己的数组实例,并且修改一行不会影响其他行。因此,修改 matrix[1][1] = 5;
将正确地为您提供:
[[0, 0, 0], [0, 5, 0], [0, 0, 0]]
Array.fill()
的这种行为填充了对同一对象(在本例中为内部数组)的引用,这是在 JavaScript 中使用嵌套数组和对象时常见的混乱来源。