fill会引发引用共享,因其仅复制引用类型值的内存地址而非创建新实例,导致多个数组元素指向同一对象,修改任一元素将同步影响其余元素。

为什么 fill 会引发引用共享
fill 方法不创建新值,只是把同一个值的引用复制到数组每个位置。原始类型(如数字、字符串)按值传递,复制的是实际内容;但对象、数组等引用类型复制的是内存地址。所以 new Array(3).fill([]) 实际只生成一个空数组,再把它地址写进三个槽位——结果是三个索引都指向同一块内存。
这个 Bug 的典型表现
一旦修改其中任一元素,所有位置同步变化:
-
二维数组错乱:比如
const mat = new Array(3).fill([]); mat[0].push('x');后,mat[1]和mat[2]也包含'x' -
React 表单字段联动:用
Array(5).fill({ value: '' })初始化表单项,改第一个字段,其余四个的value也跟着变 -
状态重置失效:调用
arr.fill({ count: 0 })本意是重置,结果所有项仍共用一个对象,后续任何更新都会污染全部
安全初始化引用类型数组的三种方式
核心原则:确保每次赋值都执行一次构造逻辑,不复用已有引用。
-
推荐用 Array.from:语义清晰,天然隔离。例如
Array.from({ length: 4 }, () => ({}))或Array.from({ length: 3 }, () => []) -
fill + map 组合:先填占位值(如
null或undefined),再用map创建新实例。例如new Array(5).fill(null).map(() => ({ id: Math.random() })) -
显式循环:兼容性最好,逻辑最直白。例如
const arr = []; for (let i = 0; i
哪些写法必须避免
以下看似简洁,实则埋雷:
-
Array(3).fill({})—— 所有对象共享同一引用 -
Array(4).fill([])—— 所有子数组指向同一数组 -
Array(2).fill(new Date())—— 两个元素记录的是同一时刻(毫秒数相同且无法独立更新) -
Array(3).fill().map(() => [])——fill()不传参时填undefined,但空位数组的map不遍历,结果仍是空数组










