先记住这个答案
普通数组的空位表示该索引没有自有属性,显式 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。
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。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。