JavaScript如何区分数组显式赋值undefined与未初始化空槽
如何区分数组中显式赋值的undefined与未初始化空槽
问题复现代码如下:
let a = Array(3); a[0] = 1; a[1] = undefined; function test(arr) { return arr.map(a => !!a); } console.log('before', a); // [1, undefined, undefined] console.log('after', test(a)); // [true, false, undefined]
造成这个差异的核心逻辑很简单:数组的未初始化空槽(稀疏数组的“洞”)本质是对应索引位置没有创建任何自有属性,而显式赋值的undefined是该索引下真实存在的属性,只是属性值为undefined。map、forEach等数组原生迭代方法会默认跳过不存在属性的空槽,不会执行回调,因此才会出现结果里第三个元素直接返回undefined、没有被转成false的情况。
准确判断方法
- 最简便可靠的方案是调用数组的
hasOwnProperty方法,传入要检测的索引:如果返回true,说明该位置是显式赋值的有效值(哪怕值就是undefined);如果返回false,说明该位置是未初始化的空槽。
const a = Array(3); a[0] = 1; a[1] = undefined; console.log(a.hasOwnProperty(0)); // true 已赋值的有效元素 console.log(a.hasOwnProperty(1)); // true 显式赋值undefined的有效元素 console.log(a.hasOwnProperty(2)); // false 未初始化的空槽
- 也可以通过
Object.getOwnPropertyNames获取数组所有自有属性的索引列表,判断目标索引是否存在于列表中,判断逻辑和hasOwnProperty完全一致:
const existIndexes = Object.getOwnPropertyNames(a); console.log(existIndexes); // ['0', '1'] 索引2不在列表中,对应位置是空槽
避坑提醒
- 不要用
arr[index] === undefined做判断,空槽和显式赋值的undefined通过取值操作拿到的结果都是undefined,完全无法区分。 - 不要依赖迭代方法是否跳过元素作为判断依据,这类写法属于利用方法副作用做检测,可读性差、性能更低,不适合作为常规判断方案。
内容的提问来源于stack exchange,提问作者Dmitry Klishev
相关产品推荐
相关产品推荐

