JavaScript稀疏数组

本文最后更新于 2025年9月9日 下午

参考:https://juejin.cn/post/6975531514444562462

new Array(len)

1
2
3
4
const arr = new Array(5);
console.log(arr); // [empty × 5]
console.log(arr.map); // ƒ map() { [native code] }
console.log(arr.length); // 5

使用 new Array(len) 创建的数组中,Array 相应的方法和属性都存在,但数组中的元素都是“空”。在 ECMAScript 标准中介绍了 new Array(len) 做了什么,精简一下主要干了这几件事:

  • 判断 len 是否为合法数字(小于 2^32 - 1 的正整数),如果不是则抛出错误
  • 创建一个 JavaScript Array 实例
  • 将这个实例对象的 length 属性设置为入参的值

其实 const arr = new Array(len) 相当于 const arr = []; arr.length = len。但数组中此时并没有包含任何实际的元素,而且不能理所当然地认为它包含 len 个值为 undefined 的元素。

empty VS undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const arr = new Array(2),
undefinedArr = [undefined, undefined];

console.log(arr); // [empty × 2]
console.log(undefinedArr); // [undefined, undefined]

arr[0]; // undefined
undefinedArr[0]; // undefined

arr.forEach((item) => {
console.log(item);
}); // 无输出
undefinedArr.forEach((item) => {
console.log(item);
}); // 输出两个 undefined

console.log(arr.hasOwnProperty(0)); // false
console.log(undefinedArr.hasOwnProperty(0)); // true

arr 和 undefinedArr 只有在访问单个具体元素时表现一致,在其他一些情况下大都不一样。

至于为什么 arr 在访问具体单个元素时返回 undefined,可以从 JS 引擎解析的角度去看。在 v8 源码上对于 empty 的描述是一个空的对象引用,但 JS 基本类型中并无这种类型,故用 undefined 来代替。这种表现就像我们在控制台访问一个不存在变量时,通常得到的就是 undefined。arr 由于没有任何实际的元素,所以 forEach 的 callback 并不会执行,而 undefinedArr 是有填充值的。

稀疏数组和密集数组

应当把 arr 和 undefinedArr 细分为两类数组,前者为稀疏数组,后者为密集数组:

  • 稀疏数组:索引不连续,数组长度大于元素个数的数组。可以简单理解为有 empty 的数组
  • 密集数组:索引连续,数组长度等于元素个数的数组。绝大部分数组是此类数组

相互转换

  • 稀疏数组 => 密集数组
1
2
3
4
5
6
7
8
9
10
const arr = new Array(5); // 稀疏数组
// [empty × 5]

// ES5 方法(方法已经被废弃)
Array.apply(null, arr); // 生成密集数组
// [undefined, undefined, undefined, undefined, undefined]

// ES6 方法
Array.from(arr); // 生成密集数组
// [undefined, undefined, undefined, undefined, undefined]
  • 密集数组 => 稀疏数组
1
2
3
4
5
const arr = [2, 3, 4, 5, 6]; // 密集数组
// [2, 3, 4, 5, 6]

arr.length = 10; // 生成稀疏数组
// [2, 3, 4, 5, 6, empty × 5]

创建稀疏数组

1
2
3
4
5
6
7
8
9
// 1
const arr1 = [];
arr1.length = 5;

// 2
const arr2 = new Array(5);

// 3
const arr3 = [, , , , ,];

稀疏数组特性

  • 稀疏数组在大多数遍历数组方法中,回调函数遇到“空”元素不会执行(会跳过)
  • 稀疏数组在访问元素的速度上比密集数组慢
  • 稀疏数组在一些数组方法中与密集数组存在差异

JavaScript稀疏数组
https://xuekeven.github.io/2021/09/06/JavaScript稀疏数组/
作者
Keven
发布于
2021年9月6日
更新于
2025年9月9日
许可协议