Javascripts Array.fill() 特殊行为[重复]

问题描述 投票:0回答:1

为什么输出这么奇怪! 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); 

javascript arrays ecmascript-6
1个回答
-4
投票

您所看到的行为是由于

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 中使用嵌套数组和对象时常见的混乱来源。

© www.soinside.com 2019 - 2024. All rights reserved.