前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库JavaScript 稀疏数组空位与 undefined 区别
JSJavaScript数组与集合

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

两个位置读出来都像是 undefined,不代表它们拥有相同的属性结构。

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

把值读取与属性结构分开

  1. 自有属性索引是否真实属于当前数组
  2. 属性查找读取和 in 可能继续查原型链
  3. 方法行为回调前是否检查属性、结果是否保留空位

下面的普通数组例子不在原型上添加索引。遇到自定义原型或代理时,必须按实际属性查找与拦截行为分析。

核心回答

先记住这个答案

普通数组的空位表示该索引没有自有属性,显式 undefined 则是存在一个值为 undefined 的属性。在没有同名原型索引时,两者读取值相同,但 map、forEach 等方法通常跳过空位而处理显式 undefined;map 会保留相应缺口,filter 会收集实际通过的元素。new Array(n) 只建立长度,因此直接 map 常常不执行回调,初始化可用 fill 或 Array.from。判断自身位置是否存在应使用 Object.hasOwn,in 还会检查原型链。JSON 不支持数组空位语法,序列化空位和 undefined 都会失去原区别。

  • 长度包含缺失索引,不能等同记录数量
  • Object.hasOwn 与 in 的原型范围不同
  • map 跳过空位,fill 可以写入真实索引

相同读取值可以对应不同结构

下面一个数组只有长度,另一个明确写入 undefined。用 Object.hasOwn 能区分自有索引,而单独比较值则不能;map 的调用次数进一步展示了这个结构差异怎样影响后续处理。

示例还把稀疏数组展开成新数组,缺失位置被普通数组迭代器读成 undefined,再写为实际元素。JSON 输出里的 null 是序列化规则造成的,不能据此说展开直接生成了 null。

检查属性、回调次数与展开结果JavaScript
const sparse = new Array(2);
const explicit = [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];
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,随后 JSON 把它编码成 null;Array.from 的映射则为每个位置主动生成实际数值。

初始化数字与初始化对象需要不同写法

固定计数数组可以先 Array(n).fill(0),因为零是可以安全重复使用的原始值。需要每行独立对象时,应使用逐项工厂;fill({}) 会让所有位置共享同一个对象,产生另一类初始化错误。

缺失数据也不一定应该自动补零。若空位代表尚未采集的测量,补零会改变统计含义,应该保留明确缺失标记并在聚合时处理。初始化工具只能填结构,不能替业务决定默认值含义。

原型查找和 JSON 会改变直觉

map 等方法的属性存在检查可能找到继承的数字属性,因此“没有自有索引就一定不调用回调”需要普通原型环境这一前提。Object.hasOwn 检查自身,in 检查整个原型链,二者不应当作完全等价。

合法 JSON 数组不能写成 [1,,3],那是 JavaScript 字面量中的空位语法。JSON.stringify 会把数组空位与 undefined 编码为 null,往返后无法还原原本缺失结构;需要保留位置状态时应设计显式表示。

回答前,多想一步

容易答错的地方

用 arr[i] 等于 undefined 判断空位
这同时匹配显式 undefined,而且读取可能来自原型或访问器。需要自身结构时使用 Object.hasOwn,再单独检查值;不要把属性是否存在与属性值是什么合并成一个判断。
把所有数组方法说成跳过并保留空位
不同方法行为不同:map 可保留结果缺口,filter 收集通过项,展开和 values 通常逐位置读取。应针对具体方法分析,不能用新旧 API 的简单口诀替代真实契约。
试着用自己的话回答

面试官还会怎么问?

delete 一个数组元素会让长度减少吗?

删除索引属性通常留下空位而不自动收缩 length;需要移除并移动后续元素应使用相应数组操作。应分别检查长度、索引存在性和业务顺序,避免删除后统计仍把缺口当记录。

空位数组调用 reduce 会怎样?

没有初值且找不到存在元素时会抛错,提供初值则可直接返回初值。长度非零并不能证明有可用起点,因此聚合应明确空输入和缺失值规则,不能只检查 length。

从接口接收数组还会遇到空位吗?

合法 JSON 本身不会传递空位语法,但客户端随后删除属性、扩展 length 或构造稀疏数组都可能产生它。应沿数据处理链定位结构变化,不要把所有缺口归因于服务器直接返回非法 JSON。

从一道题,走向一组知识

把知识连起来

数组与集合

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

掌握填充范围与对象引用,正确初始化固定长度内容。

数组与集合

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

解释转换过程如何为缺失位置写入显式值。

数组与集合

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

检查长度非零但没有可用累加器时的失败边界。

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

参考资料

  • MDN:Array 与空位
  • MDN:fill

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

本题目录
  1. 先记住这个答案
  2. 相同读取值可以对应不同结构
  3. 初始化数字与初始化对象需要不同写法
  4. 原型查找和 JSON 会改变直觉
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

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

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