JS怎么声明和初始化一个二维数组?

2023/7/31

在刷 leetcode 时,有时候需要二维数组来存数据,那对于不是强类型语言的JS,应该怎么声明和初始化一个二维数组呢?

可能你会想到通过一个一维数组数组来fill一个一维数组来实现👇 因为我一开始也是这么写的😄

const arr = new Array(2).fill(new Array(2).fill(0));
console.log("arr: ", arr);
// arr:  [ [ 0, 0 ], [ 0, 0 ] ]

arr[0][0] = 1;
console.log("arr: ", arr);
// arr:  [ [ 1, 0 ], [ 1, 0 ] ]

但这是不对的,你确实是声明和初始化了一个二维数组,但当你想要修改二维数组中的某个元素时(比如arr[0][0]),会修改第1列的所有元素

MDN上对fill的部分描述如下

fill(value)

Value to fill the array with. Note all elements in the array will be this exact value: if value is an object, each slot in the array will reference that object.

意思就是fill的值是一个exact value, 如果你传值那就是精确的值,没什么问题,但如果你传一个引用数据类型,比如数组和对象,那这个数组中的每一个fill的地方都将引用这个数据,fill的其实是地址

所以fill用来初始化值很好,但是构建二维数组这个工作就别让他干了

关于fill方法,还有一个点需要注意的是,在空数组(length = 0)上使用fill是没用的,因为数组没有什么可修改的。所以如果你要用fill,那就写上数组的长度

# fill + map

正确的声明和初始化方法就是fill配合map,初始化用fill,声明用map

const arr = new Array(2).fill(0).map(() => new Array(2).fill(0));
console.log("arr: ", arr);
// arr:  [ [ 0, 0 ], [ 0, 0 ] ]

arr[0][0] = 1;
console.log("arr: ", arr);
// arr:  [ [ 1, 0 ], [ 1, 0 ] ]

new出来一个一维数组(对应二维数组的行),然后map把数组中的每一项用一个一维数组返回(对应二维数组的列

# Array.from + fill

利用Array的静态方法from来实现

MDN上的描述👇

The Array.from() static method creates a new, shallow-copied Array instance from an iterable or array-like object.

把一个类数组对象或可迭代对象浅复制成一个新的正儿八经的Array

const arr = Array.from(new Array(2), () => Array(2).fill(0))
console.log("arr: ", arr);
// arr:  [ [ 0, 0 ], [ 0, 0 ] ]

arr[0][0] = 1;
console.log("arr: ", arr);
// arr:  [ [ 1, 0 ], [ 1, 0 ] ]

from的第一个参数就是要操作的类数组对象或者可迭代对象(对应二维数组的行

第二个参数传入一个回调,要添加到最后的数组中的每个值都将首先执行该回调,返回值添加到正儿八经的Array中(对应二维数组的列

How to love
Lil Wayne