JS数组字面量与Array.fill()创建数组的赋值行为差异原因
核心原因
两种写法创建的二维数组,内层数组的引用关系完全不同:
- 字面量写法
let arrLiteral = [[0,0,0],[0,0,0],[0,0,0]]创建时,外层数组包含的3个内层数组是完全独立的3份实例,各自占用独立内存,修改其中某一个内层数组的元素,不会对另外两个内层数组产生任何影响,这也是符合常规预期的行为。 Array(3).fill(Array(3).fill(0))的写法踩了fill方法的特性坑:fill接收的参数如果是对象/数组这种引用类型,它不会自动复制多份实例,只会把同一个内存引用填充到数组的每一个位置。也就是说这行代码执行时,只创建了1个[0,0,0]的内层数组,外层数组的3个下标arrFill[0]、arrFill[1]、arrFill[2]全指向这同一个数组。你修改任何一个下标对应的内层数组元素,本质都是在改这唯一的一个数组,三个位置的输出当然会完全同步。
对应代码的实际执行过程
循环里给arrFill赋值的过程,本质是反复覆盖同一个数组的值:
- 第一层循环i=0(对应字符串"abc"):给这个共享数组的0、1、2位依次赋值'a'、'b'、'c',此时打印arrFill的三个元素,全是
['a','b','c'] - 第一层循环i=1(对应字符串"def"):又给同一个共享数组的0、1、2位依次覆盖成'd'、'e'、'f',此时三个元素全变成
['d','e','f'] - 第一层循环i=2(对应字符串"g"):字符串长度只有1,只把共享数组的0位覆盖成'g',剩下1、2位保留之前的'e'、'f',最终这个共享数组的值就是
['g','e','f'],三个下标指向同一个数组,就出现了你看到的异常输出。
正确的多维数组创建方式
如果想用非字面量的方式生成内层独立的二维数组,不要直接给fill传引用类型值,可以搭配映射回调,让每个位置都生成新的独立数组:
// 方式1:用Array.from的映射回调,每次循环生成新数组 let arr1 = Array.from({ length: 3 }, () => Array(3).fill(0)) // 方式2:先用基础值fill占位,再map返回新的内层数组 let arr2 = Array(3).fill(null).map(() => Array(3).fill(0))
这两种写法生成的二维数组,每个内层数组都是独立实例,赋值表现和字面量创建的数组完全一致。
内容的提问来源于stack exchange,提问作者KamilaW
相关产品推荐
相关产品推荐

