fill() 初始化二维数组时因浅拷贝导致所有行引用同一子数组,正确做法是用array.from()或fill().map()确保每行独立;填充对象同理需在回调中创建新实例,并注意稀疏数组问题。

fill() 初始化二维数组时为什么只生成一层引用
直接用 Array(3).fill(Array(4).fill(0)) 看似简洁,实际所有行都指向同一个子数组。修改 grid[0][1] 会同步影响 grid[1][1] 和 grid[2][1] —— 这是 fill() 对对象(包括数组)只做浅拷贝导致的。
正确创建独立子数组的两种可靠写法
必须让每行都是新数组实例。推荐以下任一方式:
-
Array.from({ length: 3 }, () => Array(4).fill(0)):利用Array.from()的映射回调,每次调用都新建子数组 -
Array(3).fill(null).map(() => Array(4).fill(0)):先填占位值(如null),再用map()替换为新数组
两者性能接近,Array.from() 语义更清晰;fill().map() 兼容性略好(IE11+)。
用 fill() 填充非原始值(如对象)要格外小心
若网格单元需默认对象(如 { id: null, status: 'idle' }),不能写 Array(3).fill(Array(4).fill({ id: null })) —— 子数组里每个元素都会引用同一个对象。正确做法是:
- 用
Array.from({ length: 3 }, () => Array.from({ length: 4 }, () => ({ id: null, status: 'idle' })) - 或嵌套
map():Array(3).fill(null).map(() => Array(4).fill(null).map(() => ({ id: null, status: 'idle' }))
关键点:每个单元格的初始化逻辑必须在回调函数内执行,确保独立实例。
fill() 在稀疏数组中不生效,初始化前先确保数组已“致密”
Array(5) 创建的是长度为 5 的稀疏数组(无实际索引属性),此时调用 .fill(0) 会正常填充;但若中间曾 delete 过元素或用负索引赋值,可能残留空槽。保险起见:
- 用
Array(5).fill(undefined)或new Array(5).fill(0)明确构造致密数组 - 避免混用
arr[10] = x和fill()—— 前者会扩大数组并留空槽,fill()不会触碰这些空槽
稀疏性问题在动态构建网格时容易被忽略,尤其配合 push 或 delete 操作后。










