JS专项突破:数组的底层原理---快数组与慢数组在JS中数组存在两种形式:快数组与慢数组。 本文专门对快数组与慢数组进行
在JS中数组存在两种形式:快数组
与慢数组
。
创建数组的常见方案
在了解这两个之前,需要先复习一下数组的创建方式:
- 字面量创建
- 使用构造函数直接创建
- 使用
new
关键字实例化构造函数创建
// 字面量创建
const arr = [];
// 使用构造函数创建
const arrForConsuctor = Array(10);// [10 * Empty]
const arrForConsuctor1 = Array(1,2,3);// [1, 2, 3]
// 使用new 关键字实例化构造函数
const arrInstance = new Array(10);// [10 * Empty]
const arrInstance1 = new Array(1,2,3);// [1, 2, 3]
以上就是创建数组的常见方案了,其他方案还有:
Array.from(Array(10))
Array.apply(null, Array(10))
- ...
基础概念普及
稀疏数组
稀疏数组
其实指的就是那些数据在内存中不连续的数组,即数组的长度大于元素的个数。
在JavaScript中,创建有长度的数组时,会看到Empty
,当创建数组后,没有给具体内容时,就会展示Empty
对位置进行占位。
当这个Empty
出现在某个部分赋值的数组中间时,这便可以称其为空隙
。
而
稀疏数组
就是存在空隙
的数组。 稀疏矩阵中Empty
,描述的是一个空对象的引用。 它可以等于undefined
,但JS的一些API则是对它有不同的行为处理,如:
indexOf``filter``forEach``every``some``flatMap
会默认忽略掉Empty
- 而
includes
如果判断为undefined
时,则会返回true【实际上,判断空数组时也会返回true】for-in
只会遍历可枚举属性,不会遍历稀疏数组中的Empty
for-of
则可以遍历Empty
- 使用
map
方法时,则会保留Empty
join``sort
方法不会忽略Empty
密集数组
密集数组
则是元素中不存在空隙
的数组。
直接生成密集数组:
const arr1 = [...new Array(1024)];//[undefined, undefined ...]
const arr2 = Array.apply(null, new Array(1024));//[undefined, undefined ...]
const arr3 = Array.from(new Array(1024))//[undefined, undefined ...]
快数组
在JavaScript中快数组
其实就是在内存中开辟一片连续的内存区域用来存储数据,这种连续的内存
在数组便利时,遍历效率会高
很多,但同时由于快数组内存是连续的,因此可能需要开辟一大块内存供其使用,其中很有可能会开辟一块完整的大内存
,其中很有可能没有完全使用到,从而可能出现内存浪费
的情况。
关键词:内存是连续的``遍历效率高``内存浪费
创建快数组的方式
当初始化时,可以直接初始化固定长度的密集数组,这时就会创建快数组
:
const LENGTH = 1024 * 1024 * 5;
const arr = new Array(LENGTH);
for(let i = 0; i < LENGTH; i++) arr[i] = i;
// 这时的arr就是快数组
看到这里时,可能会问:“如果我不连续的插入值时,创建的是什么数组?
”
这里就要考虑插入时,数组的稀疏程度了,如果稀疏的程度不高
时,我们创建的依旧是快数组
:
const LENGTH = 1024 * 1024 * 5;
const arr = new Array(LENGTH);
// 这里只会在偶数下标的位置插入值
for(let i = 0;i < LENGTH; i+=2) arr[i] = i;
// 这里依旧是快数组
有的人看到这里,可能还会有疑问:“如果我插入不同类型的数据,那么数组这时是不是就是慢数组了呢?
”
其实不然,在JavaScript中,数组的类型不会影响数组的性质,当我们创建了快数组
后,即使插入了不同类型的数据也不会影响其性质。
const LENGTH = 1024 * 1024 * 5;
const arr = new Array(LENGTH);
for(let i = 0;i < LENGTH; i++){
switch(i){
case i % 5:{
arr[i] = true;
break;
}
case i % 2:{
arr[i] = i;
break
}
default:{
arr[i] = `${i}`;
break;
}
}
}
// 这里依旧是快数组
慢数组
而在JavaScript中慢数组
,则是使用了HashTable
的数据结构,它类似于一种对象的结构,只不过对象的索引是数字【而数字作为索引key
时会被强制转换为字符串】,并且其对应的数据分配的内存非常零散
,其好处是可以节省内存
,但是遍历效率却会慢
上许多;。
关键词:内存是分散的
节省内存
遍历效率低
快慢数组转换
快数组转慢数组
一般快数组
转慢数组
一般都是因为数组扩容原因:
- 在快数组扩容时,新容量大于当前容量一定倍数时
【即当前容量的 3 * 3倍时】
,快数组将会转变为慢数组。 - 当新增的数据位置所在的下标减去
当前快数
组最大容量大于等于1024时,则会转换为慢数组。
慢数组转快数组
而慢数组转为快数组的条件则是在操作数组时,当慢数组检测节省空间小于等于50%时,即使用稀疏数组节省空间并没有节省很多空间时,这时慢数组则会转为快数组。
源码
数组类型转换:
转载自:https://juejin.cn/post/7414416537375064091