刷算法题的时候,应该经常遇到提前声明一个二维数组的情况,常常会使用到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]
只有被操作的元素,数值改动了。
大功告成!