JavaScript稀疏数组与密集数组

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

参考: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 相应的方法、属性都存在,但数组中的元素是「empty」。

在 ECMAScript 标准中介绍了new Array(len)做了什么,精简一下主要干了这几件事:

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

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

emptyVSundefined

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 细分应该是两类数组,arr 类的为稀疏数组 ,undefinedArr 类的为密集数组。

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

相互转换

  • 稀疏数组 => 密集数组
1
2
3
4
5
6
7
8
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
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
// 1
const arr1 = [];
arr1.length = 5;
// 2
const arr2 = new Array(5);
// 3
const arr3 = [, , , , ,];

稀疏数组特性

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

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