fill({})会共享同一对象,因对象按引用传递,所有数组元素指向同一内存地址;修改任一元素属性会影响全部,可用array.from替代确保独立实例。

因为 fill() 对对象只复制引用,不创建新实例——所有数组元素指向同一块内存,改一个,全跟着变。
为什么 fill({}) 会共享同一个对象?
fill(value) 的行为是“把 value 这个值写进每个位置”。JavaScript 中:
- 基本类型(如
0、'a'、true)按值传递,每次写入都是独立副本; - 对象(包括
{}、[]、new Date())按引用传递,fill({})实际是把同一个内存地址复制了 N 次。
结果就是:数组里所有元素都“看着同一份数据”,不是三个空对象,而是三个指向同一个空对象的指针。
怎么一眼看出是不是掉坑里了?
出现以下任一现象,基本可以确认存在引用共享:
- 修改
arr[0].name = 'Alice'后,arr[1].name也变成'Alice'; -
arr[0] === arr[1]返回true; - 在浏览器调试器中展开数组,多个对象旁显示
Object {…} (same as #1); - 用
fill([])创建二维数组,改grid[0][0],grid[1][0]也跟着变。
安全替代方案有哪些?
核心原则:让每次填充都执行一次构造逻辑,确保每个元素是全新对象。
-
推荐用
Array.from:Array.from({ length: 3 }, () => ({}))或Array.from({ length: 4 }, () => []); -
传统循环也可靠:
const arr = []; for (let i = 0; i ; -
避免绕弯写法,比如
Array(3).fill(null).map(() => ({}))—— 多了一步 fill 占位,不如直接用Array.from清晰。
二维数组初始化的典型错误
错误写法:Array(3).fill(Array(4).fill(0)) —— 外层数组的 3 个元素都指向同一个子数组。
正确写法:Array.from({ length: 3 }, () => Array.from({ length: 4 }, () => 0)),或嵌套循环。
哪怕只是填空数组:Array.from({ length: 5 }, () => []) 才真正生成 5 个互不影响的独立数组。











