JavaScript中两种二维矩阵创建方式的差异问题分析
为什么用
Array.fill()创建二维数组会导致所有子数组同步变化? 核心原因和new关键字无关,问题出在引用类型的特性和Array.fill()的工作逻辑上:
1. dp1的异常根源
const dp1 = new Array(6).fill(new Array(4).fill(0));
这里new Array(4).fill(0)只会执行一次,生成唯一的一个数组实例。fill()方法的作用是把这个数组的内存引用,填充到外层数组的每一个索引位置。也就是说,dp1[0]、dp1[1]……dp1[5]指向的是同一个数组对象。
当你在循环中执行dp1[i][j] = ${i}, ${j}``时,本质上是在反复修改同一个底层数组:
- 先修改
dp1[5][j],此时所有子数组都会同步显示这个值 - 接着修改
dp1[4][j],覆盖之前的内容,所有子数组再次同步更新 - 直到最后修改
dp1[0][j],所有子数组最终都会显示这一轮的赋值结果,也就是你看到的全是['0, 0', '0, 1', '0, 2', '0, 3']。
你可以通过下面的代码验证引用相同:
console.log(dp1[0] === dp1[1]); // 输出 true,说明是同一个数组
2. dp2符合预期的原因
const dp2 = new Array(6); for (let i = 0; i < 6; i++) { dp2[i] = new Array(4).fill(0); }
循环的每一次迭代中,new Array(4).fill(0)都会生成一个全新的数组实例,每个实例都有独立的内存地址。dp2[0]到dp2[5]各自指向不同的数组,修改其中一个不会影响其他子数组,所以最终每个子数组的内容都是独立的。
验证引用独立的代码:
console.log(dp2[0] === dp2[1]); // 输出 false,说明是不同数组
3. 用fill()创建二维数组的正确写法
如果想一行代码创建独立的二维数组,可以结合map()方法,让每个外层数组元素都对应新的子数组:
const dp1 = new Array(6).map(() => new Array(4).fill(0));
map()会遍历外层数组的每个位置,每次回调都生成一个新的子数组,避免了引用共享的问题。
内容的提问来源于stack exchange,提问作者Kakamotobi
相关产品推荐
相关产品推荐

