前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库fill 方法负数 start end 参数
JavaScript数组与集合

Array.fill 传负数的 start、end 怎么换算?为什么最后一项没被填上?

fill(value, start, end) 填充的是 [start, end),包含起点、不包含终点。负数先加上 length 再算,长度为 5 时 -3 是下标 2、-1 是下标 4,所以只填下标 2 和 3,最后一项不在范围里。想填到末尾,就省略 end。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#数组与集合
先看核心答案读代码示例
理解线索

`fill` 的区间怎么算出来

  1. 负数换算start 或 end 为负时加上 length,比如 -1 就是 length - 1
  2. 边界裁剪换算后小于 0 按 0 算,大于 length 按 length 算
  3. 左闭右开实际填充下标 start 到 end - 1,其中 end 默认是 length

fill 不会让数组变长。new Array(3).fill(0) 能用,是因为 new Array(3) 已经有长度 3,fill 只是把三个空位填上。

核心回答

先记住这个答案

fill(value, start, end) 会修改原数组,把下标从 start 到 end - 1 的位置都设成 value,也就是左闭右开区间。负数参数先加上数组长度换算,换算后超出 0 到 length 的部分会被裁剪到边界。长度为 5 时,start 为 -3 换算成 2,end 为 -1 换算成 4,于是只填下标 2 和 3,下标 4 是终点,不包含在内。省略 start 从 0 开始,省略 end 一直填到末尾;终点不大于起点时什么都不填。

  • 区间左闭右开,end 那一项不会被填
  • 负数加上 length 换算,超出范围就裁剪到边界
  • 终点不大于起点时一个都不填
  • fill([]) 让每一格指向同一个数组

负数和越界的几种情况

把几种参数组合放在一起跑,规则就很清楚了。

区间换算和裁剪JavaScript
const arr = [0, 0, 0, 0, 0]
console.log(JSON.stringify(arr.fill(1, -3, -1))) // 换算成 fill(1, 2, 4)

console.log(JSON.stringify([0, 0, 0].fill(9, 2, 1))) // 终点小于起点,不填
console.log(JSON.stringify([0, 0, 0].fill(9, -10))) // -10 + 3 = -7,裁剪到 0
console.log(JSON.stringify([0, 0, 0].fill(9, 1, 10))) // 10 超出长度,裁剪到 3
查看输出与解释
[0,0,1,1,0]
[0,0,0]
[9,9,9]
[0,9,9]

第一行就是题目里的情况:-1 代表的是「最后一项」这个位置,但它作为 end 是不包含的,所以最后一项没被填。想从倒数第三项一直填到最后,写 arr.fill(1, -3),不传 end。 左闭右开的好处是 end - start 正好等于填充的个数,slice、copyWithin、substring 用的都是这套规则。记住一个,其它的就都会了。

用对象填充时的共享引用

fill 只计算一次 value,然后把同一个值放到每个位置上。值是数字、字符串时没问题,是对象或数组时,所有格子都指向同一个对象。

用 fill([]) 初始化二维数组JavaScript
const grid = new Array(3).fill([]) // 三格是同一个数组
grid[0].push('x')
console.log(JSON.stringify(grid))

const grid2 = Array.from({ length: 3 }, () => []) // 每次调用都新建一个
grid2[0].push('x')
console.log(JSON.stringify(grid2))
查看输出与解释
[["x"],["x"],["x"]]
[["x"],[],[]]

grid 看起来有三行,其实是同一行被放了三次,往第一行 push,三行一起变。这个 bug 在初始化棋盘、矩阵、分组列表时很常见。改用 Array.from 并传入一个工厂函数,每个位置都会调用一次函数,拿到各自独立的新数组。

fill 会填上空位
new Array(3) 创建的是三个空位,map 会跳过空位,所以 new Array(3).map(() => 0) 得到的还是空位。fill 不管这个位置有没有值,都会直接赋值,所以 new Array(3).fill(0) 能得到 [0, 0, 0]。这是 fill 最常见的用途。
回答前,多想一步

容易答错的地方

以为 -1 作为 end 会包含最后一项
-1 换算成 length - 1,它是终点,不包含。这个误解和把 slice(0, -1) 当成「复制整个数组」是同一个问题,其实 slice(0, -1) 会去掉最后一项。
以为 fill 返回新数组
fill 修改原数组并返回原数组本身。在 React 里对状态数组直接 fill,会改掉原状态。需要新数组时写 [...arr].fill(v),或者 Array.from({ length: n }, () => v)。
以为 fill 能扩展数组
[].fill(0, 0, 5) 得到的还是空数组,因为 end 被裁剪到了 length,也就是 0。要指定长度,得先用 new Array(5) 或 Array.from({ length: 5 }) 把长度撑起来。
试着用自己的话回答

面试官还会怎么问?

怎么初始化一个 3 行 4 列、全是 0 的二维数组?

Array.from({ length: 3 }, () => new Array(4).fill(0))。外层用 Array.from 保证每一行是独立的数组,内层的元素是数字,用 fill 没有共享问题。

start 传小数或者字符串会怎样?

会先转成整数,小数向零截断,fill(1, 1.8) 等于 fill(1, 1);字符串 '2' 会被转成数字 2;转换后是 NaN 的按 0 处理。实际代码里不建议依赖这种隐式转换。

类数组对象能用 fill 吗?

可以借用,比如 Array.prototype.fill.call({ length: 3 }, 0),它会按 length 在对象上写下 0、1、2 三个属性,返回的还是那个对象,不是数组。

从一道题,走向一组知识

把知识连起来

数组与集合

arr.at(-1) 和 arr[-1] 有什么区别?越界和旧浏览器怎么办?

at 取单个元素时也是负数加 length,但越界时返回 undefined,不像 fill 那样裁剪。

数组与集合

稀疏数组的空位和 undefined 有什么区别,为什么 Array(n).map 不执行?

map 会跳过空位而 fill 不会,所以初始化数组时常写 new Array(n).fill(0)。

参考资料

  • MDN:fill

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 负数和越界的几种情况
  3. 用对象填充时的共享引用
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑