JS中new Array与[]的行为差异:为何二维数组操作结果不同?
两段JS代码结果差异的原因
核心问题出在数组引用的复用上,拆解细节如下:
第一段代码的隐藏陷阱
第一段创建foo的过程里,关键漏洞在fill方法的使用:
const foo = new Array(2) .fill(new Array(2)) // 问题根源 .map((subArr) => subArr.fill(0));
- 调用
fill(new Array(2))时,只会生成一个子数组实例,然后把这个子数组的引用填充到父数组的两个位置中。也就是说,foo[0]和foo[1]指向的是同一个数组对象,只是看起来是两个独立的子数组。 - 后续的
map遍历中,两次执行subArr.fill(0)都是在修改同一个数组,最终foo的两个元素依然共享同一个引用。
执行splice操作时:
const result = foo.map((subArr, index) => { subArr.splice(index, 1, 1); return subArr; });
- 第一次遍历(index=0):修改共享子数组,将索引0的值改为1,数组变为
[1, 0]。 - 第二次遍历(index=1):还是修改这个共享子数组,将索引1的值改为1,数组变为
[1, 1]。 - 最终
result里的两个元素都是被修改两次的共享数组,所以输出[[1, 1], [1, 1]]。
第二段代码的正常逻辑
第二段直接初始化foo:
const foo = [[0, 0], [0, 0]];
这里的两个[0, 0]是完全独立的数组实例,foo[0]和foo[1]指向不同的数组对象。
执行splice操作时:
- 第一次遍历(index=0):修改
foo[0],将索引0的值改为1,得到[1, 0]。 - 第二次遍历(index=1):修改
foo[1],将索引1的值改为1,得到[0, 1]。 - 最终
result里是两个各自被修改的独立数组,所以输出[[1, 0], [0, 1]]。
验证引用是否相同
可以用全等运算符验证子数组的引用关系:
- 第一段代码执行
console.log(foo[0] === foo[1]),输出true(两个子数组是同一引用)。 - 第二段代码执行
console.log(foo[0] === foo[1]),输出false(两个子数组是独立实例)。
内容的提问来源于stack exchange,提问作者DivDisable
相关产品推荐
相关产品推荐

