Array.prototype.fill 填充二维数组

97 阅读1分钟

刷算法题的时候,应该经常遇到提前声明一个二维数组的情况,常常会使用到Array.prototype.fill这个方法来进行填充。

例如, 填充一个5*5的矩阵,值均为-1。凭直觉写出以下代码:

new Array(5).fill(new Array(5).fill(-1))

看控制台输出:

(5) [Array(5), Array(5), Array(5), Array(5), Array(5)]
0: (5) [-1, -1, -1, -1, -1]
1: (5) [-1, -1, -1, -1, -1]
2: (5) [-1, -1, -1, -1, -1]
3: (5) [-1, -1, -1, -1, -1]
4: (5) [-1, -1, -1, -1, -1]

看起来好像没错。

但,当我们对其中元素进行改动时,比如

a[0][1] = 5

再打印一下原数组:

(5) [Array(5), Array(5), Array(5), Array(5), Array(5)]
0: (5) [-1, 5, -1, -1, -1]
1: (5) [-1, 5, -1, -1, -1]
2: (5) [-1, 5, -1, -1, -1]
3: (5) [-1, 5, -1, -1, -1]
4: (5) [-1, 5, -1, -1, -1]

发现同一列的元素均已改变。

这是因为,当使用fill对数组进行填充时,若传入的参数为引用类型,则只是填充了该参数的引用,而不是原始值。导致操作某一元素时,其他对应元素均会改变。

正确的写法,可参考MDN的写法,即用for循环来处理二维数组的填充Array.prototype.fill() - JavaScript | MDN

const arr = new Array(3);
for (let i = 0; i < arr.length; i++) {
  arr[i] = new Array(4).fill(1); // 创建一个大小为 4 的数组,填充全 1
}
arr[0][0] = 10;
console.log(arr[0][0]); // 10
console.log(arr[1][0]); // 1
console.log(arr[2][0]); // 1

当然,还可以借助map函数。

new Array(5).fill().map(() => new Array(5).fill(-1))

同样,对其中一个元素进行操作

a[0][1] = 5

再打印一下原数组:

(5) [Array(5), Array(5), Array(5), Array(5), Array(5)]
0: (5) [-1, 5, -1, -1, -1]
1: (5) [-1, -1, -1, -1, -1]
2: (5) [-1, -1, -1, -1, -1]
3: (5) [-1, -1, -1, -1, -1]
4: (5) [-1, -1, -1, -1, -1]

只有被操作的元素,数值改动了。

大功告成!