js中初始化二维数组

有这样一个场景,需要初始化一个二维数组,自然就想到了 Array.prototype.fill 这个 API

在一维数组的初始化过程中,我们可以很自然的想到下面的方法:

1
2
// 初始化一个长度为3的二维数组并全部用0填充
const a = new Array(3).fill(0);

二维数组应该就是内部在分别填充一个数组就好了,如下:

1
const double = new Array(3).fill(new Array(3).fill(0));

然而当我们真正在测试的时候发现奇怪的事情发生了。

1
2
3
4
const double = new Array(3).fill(new Array(3).fill(0));

double[0][0] = 1;
console.log(double); // [[1,0,0], [1,0,0], [1,0,0]]

一维数组的三个子数组第一项都被改了,神奇的事情发生了,显然内部的三个子数组对象像是同一个引用。

当我们看 fill 的 MDN 文档时发现

fill(value)

fill(value, start)

fill(value, start, end)

value

Value to fill the array with. (Note all elements in the array will be this exact value.)

有三种泛型,第一个参数为 value 也就是我们要填充的值,可能是一个基本数据类型,也可能是一个引用数据类型。如果是一个引用数据类型,所有被填充的都将是这个引用数据类型的地址。也就是说如果填充引用数据类型,填充的每个元素都是同一个引用。

至此,问题解决。

那如何正确的初始化一个二维数组呢?其实在 MDN 的文档中已经给出了示例,如何创建一个全是 1 的矩阵,代码如下:

第一种方式:

1
2
3
4
5
6
7
8
9
10

const arr = new Array(3);
for (let i= 0; i < arr.length; i++) {
arr[i] = new Array(4).fill(1); // Creating an array of size 4 and filled of 1
}
arr[0][0] = 10;
console.log(arr[0][0]); // 10
console.log(arr[1][0]); // 1
console.log(arr[2][0]); // 1

其他方式

1
2
3
4
5
6
const arr1 = new Array(5).fill(0).map(() => new Array(5).fill(1));
console.log(arr1);

const arr2 = Array.from({ length: 5 }, () => new Array(5).fill(1));
console.log(arr2);

备注:

javascript 中 Array 的构造函数无论是 new Array() 还是 Array() 直接调用,两者都是一样的。

参考链接:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill
  2. https://tc39.es/ecma262/multipage/indexed-collections.html#sec-array.prototype.fill
作者

monster1935

发布于

2021-11-19

更新于

2024-09-25

许可协议