js fill填充数组

2026-05-14 04:00:19 235阅读 0评论

JS 数组 fill 方法:高效初始化背后的“引用陷阱”

做前端开发时,我们常遇到这种场景:需要初始化一个长度为 10 的数组,里面全是 0,或者全是空对象。新手习惯写 for 循环,老手会想到 new Array(10).fill(0)。这行代码看似简洁优雅,实则藏着不少容易忽视的细节,一旦用错,排查起 Bug 来十分头大。

基础用法与参数细节

Array.prototype.fill() 的核心作用很简单:将数组中指定范围的内容替换为一个固定值。语法是 arr.fill(value[, start[, end]])。其中 value 必传,startend 可选,默认从头填到尾。

最实用的地方在于它对负索引的支持。比如你想把数组最后 3 个元素置为 null,无需计算长度,直接写 arr.fill(null, -3) 即可生效。此外,范围也是左闭右开,这与切片操作 slice 保持一致,符合大多数开发者的直觉。

const arr = new Array(5).fill(0); 
// [0, 0, 0, 0, 0]

致命的“引用陷阱”

这才是这篇文章的重点。fill 的值是基本类型(如数字、字符串)时,没问题;但如果是对象或数组,所有元素将共享同一块内存地址。

很多开发者在初始化二维数组或对象列表时踩过的最大坑就在这里。比如下面这段代码:

const matrix = new Array(3).fill({ val: 0 });
matrix[0].val = 100;
console.log(matrix); 
// 输出:[{val: 100}, {val: 100}, {val: 100}]

你以为只是修改了第一个元素的属性,结果整个矩阵都变了。这是因为 fill 执行的是浅拷贝,三个位置存的都是同一个对象的引用。想要独立修改每个格子,必须配合 map 使用,确保每次生成新实例:

const safeMatrix = new Array(3).fill(0).map(() => ({ val: 0 }));

变性与替代方案

另一个常被忽略的特性是原地修改fill 不会返回新数组,而是直接改变原数组并返回该数组引用。如果你期望像函数式编程那样保持数据不可变性,这个方法就需要谨慎对待。

相比手动循环,fill 的优势在于可读性性能优化。现代浏览器对内置方法的底层优化远优于手写循环。但在处理复杂结构时,它并非万能钥匙。例如创建 [1, 2, 3] 这样的递增序列,fill 无能为力,这时候应该转而使用 Array.from({ length: 3 }, (_, i) => i + 1),既避免了引用问题,又能实现动态值的生成。

实际开发建议

在日常工作中,判断是否使用 fill 可以参考以下思路:

  1. 值类型优先:如果填充内容只是数字、布尔值或 null,放心大胆用,效率最高。
  2. 对象需谨慎:只要涉及对象、数组等引用类型,务必检查是否需要独立副本。
  3. 链式搭配:常与 map 组合使用,先定长度,再映射值,逻辑更清晰。

掌握 fill 的真正意义,不在于记住它的语法,而在于理解它如何处理内存中的“引用”。避开那个简单的对象陷阱,能让你的代码在初始化阶段就干净稳定得多。

文章版权声明:除非注明,否则均为Dark零点博客原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
验证码
评论列表 (暂无评论,235人围观)

还没有评论,来说两句吧...

目录[+]