前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
首页程序员面试题库JavaScript 稀疏数组空位与 undefined 区别
JavaScript数组与集合

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

new Array(3) 只是把长度设成了 3,索引 0 到 2 上什么都没有,这叫空位。读空位得到 undefined,但它和真的存了一个 undefined 不一样:map、forEach 会跳过空位,所以 Array(3).map(...) 一次回调都不执行。

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

读出来一样,结构不一样

  1. 空位索引上没有属性,Object.hasOwn(arr, 0) 是 false
  2. 显式 undefined属性存在,只是值是 undefined
  3. 数组方法map 和 forEach 跳过空位,展开和 for...of 会把空位读成 undefined

JSON.stringify 会把空位和 undefined 都转成 null,存一次再读回来,空位就变成了真实存在的 null。

核心回答

先记住这个答案

数组本质上是一个以索引为键的对象。空位的意思是这个索引上根本没有属性,比如 new Array(3) 只把 length 设成了 3,索引 0、1、2 都不存在。显式 undefined 则是属性存在,值是 undefined。两者读出来都是 undefined,但数组方法对待它们不同:map、forEach、filter 会跳过空位,只处理真实存在的元素。所以 new Array(3).map(() => 0) 一次回调都不会执行,结果还是三个空位。初始化数组要用 fill 或 Array.from。

  • 空位是索引上没有属性,不是存了 undefined
  • map、forEach、filter 都会跳过空位
  • 初始化用 fill 或 Array.from,别直接 map
  • fill({}) 让所有位置共享同一个对象

同样读出 undefined,结构不同

用 Object.hasOwn 检查索引上到底有没有属性,再看 map 和展开的表现。

空位、显式 undefined 和几种转换JavaScript
const sparse = new Array(2)                  // 两个空位
const explicit = [undefined, undefined]      // 两个真实的 undefined
console.log(Object.hasOwn(sparse, 0), Object.hasOwn(explicit, 0))

let calls = 0
const mapped = sparse.map(() => { calls++; return 0 })
console.log(calls, Object.hasOwn(mapped, 0)) // 回调没执行,结果还是空位

const copied = [...sparse]                   // 展开把空位读成 undefined
console.log(Object.hasOwn(copied, 0), copied[0] === undefined)
console.log(JSON.stringify(copied))
console.log(JSON.stringify(Array.from({ length: 2 }, (_, index) => index)))
查看输出与解释
false true
0 false
true true
[null,null]
[0,1]

第一行说明空位上没有属性,显式 undefined 有。第二行 map 的回调调用了 0 次,返回的 mapped 依然是空位。第三行展开运算符通过迭代器按索引逐个读取,空位读到 undefined 后写进新数组,于是变成了真实的元素。最后 Array.from 带映射函数,给每个位置都生成了实际的值,这是初始化数组最稳的写法。

初始化数组的正确写法

想生成 [0, 0, 0],写 new Array(3).fill(0)。fill 不管索引存不存在,会逐个写入,写完就没有空位了,之后再 map 就能正常工作。想生成 [0, 1, 2] 这样和索引相关的值,用 Array.from({ length: 3 }, (_, i) => i)。

fill 对象时的坑
要生成一个二维数组,写成 new Array(3).fill([]) 看起来没问题,但三个位置放的是同一个数组。往第一行 push 一个元素,三行都变了。原因是 fill 只计算一次参数,把同一个引用写到每个位置。每行都要独立的对象或数组时,用 Array.from({ length: 3 }, () => []),工厂函数每次调用都会创建新的。
回答前,多想一步

容易答错的地方

用 arr[i] === undefined 判断空位
显式存了 undefined 的位置也会返回 true,分不出来。要判断索引上有没有属性,用 Object.hasOwn(arr, i)。i in arr 也行,但它还会查原型链。
说所有数组方法都跳过空位
forEach、map、filter、reduce、some、every 会跳过空位。但 for...of、展开运算符、Array.from、find、findIndex、includes 会把空位当成 undefined 处理。join 会把空位转成空字符串。回答时要说清是哪个方法。
试着用自己的话回答

面试官还会怎么问?

delete arr[1] 之后数组长度会变吗?

不会。delete 只删掉索引 1 上的属性,留下一个空位,length 不变。要真正移除元素并让后面的元素前移,用 splice(1, 1)。

稀疏数组是怎么产生的?

除了 new Array(n),还有几种常见情况:字面量里写连续逗号 [1, , 3];给超过当前长度的索引赋值 arr[10] = 1;直接把 length 调大;对元素用 delete。JSON 本身不支持空位,接口返回的数据不会是稀疏的。

为什么不建议使用稀疏数组?

除了方法行为不一致,引擎对稀疏数组通常也无法做连续存储的优化,访问会变慢。业务里需要表示「这个位置没有数据」时,用 null 这样明确的值更清楚。

从一道题,走向一组知识

把知识连起来

数组与集合

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

fill 是给空位数组填值最常用的方法,那篇讲它的范围参数和填对象时的共享问题。

数组与集合

Array.from 能转换类数组,为什么数组展开有时却会报错?

Array.from({ length: n }) 能生成没有空位的数组,那篇讲它为什么能接收这种类数组对象。

数组与集合

为什么空数组 reduce 不传初始值会抛错,应该返回什么才合理?

全是空位的数组调用 reduce 不传初始值,会和空数组一样抛 TypeError。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • MDN:Array 与空位
  • MDN:fill

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

本题目录
  1. 先记住这个答案
  2. 同样读出 undefined,结构不同
  3. 初始化数组的正确写法
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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