稀疏数组
概念
在一些后端语言中,如 C,数组内的值一般被分配在一系列连续的内存地址上,可是在 js 中,某些数组内存则不是连续的,所谓稀疏,顾名思义,不连续,存在一些空隙;web
例如:后端
var arr = new Array(3);console.log(arr);// (3) [empty × 3]
数组
微信
app
经过以上方法建立数组,其中 Array(3)
中的参数 3 表示数组的长度,这个数组就是稀疏的,控制台输出通常带有 empty
字样,或者像下面这样建立数组:性能
var arr = [1,,2];console.log(arr);// (3) [1, empty, 2]
flex
url
spa
由于定义语句中两个逗号之间无字符,没有定义值,一样带有 empty
字样,表明稀疏数组,这里能够把 empty
理解为上面讲到的 空隙;.net
特色
接下来看一下稀疏数组特殊在什么地方,举个例子说明:
var arr1 = [1, 2, 3]; // 正常数组var arr2 = new Array(3); // 稀疏数组var arr3 = [1, , 3]; // 稀疏数组console.log(arr1.length, arr2.length, arr3.length);// 3 3 3console.log(arr2[0], arr3[1]);// undefined undefinedfor (var i = 0; i < 3; i++) { console.log(arr1[i], arr2[i], arr3[i]);}// 1 undefined 1// 2 undefined undefined// 3 undefined 3arr1.forEach(function(x){ console.log(x);});// 1// 2// 3arr2.forEach(function(x){ console.log(x);});// (无输出)arr3.forEach(function(x){ console.log(x);});// 1// 3console.log(0 in arr3, 1 in arr3);// true false
总结一下,建立的稀疏数组,其长度(length)与定义长度值一致;空隙 值能够被单独访问到,而且不是以前出现的 empty
字样,而是 undefined
,好比例子中出现 undefined
时都是使用 arr[i]
这样的索引直接访问方式;使用某些数组方法如 forEach()
时,会忽略掉空隙值,只处理正常值,因此也会使得 1inarr3
值为 false
,即数组中不存在该索引;
细想一下,js 这样处理的缘由多半是去除没必要要的性能开销,当数组至关大时,能够避免处理一些未初始化的值,但这样也同时使得开发中会出现一些问题,因此应尽可能避免;
举个例子来查看一下性能如何:
console.time('one');// 密集数组Array(...Array(1e5)).forEach(function(){ ;});console.timeEnd('one');console.time('two');// 稀疏数组Array(1e5).forEach(function(){ ;});console.timeEnd('two');// one: 26.3759765625ms// two: 5.701171875ms
能够看出在处理较大数组时,稀疏数组确实能下降很多性能开销;
密集数组
概念
与稀疏相对应,则存在密集,定义也就是元素中不存在 空隙 值,其实密集数组基本就是平时常见的正常数组;
例如:
var arr1 = [1, 2, 3];var arr2 = new Array(1, 2, 3);arr2.forEach(function(x){ console.log(x);});// 1// 2// 3
以上都是一些定义密集数组的方法,而且数组中的值都能被正常访问或遍历处理;
区别
运用时须要注意如下状况:
var arr1 = [undefined, undefined, undefined];var arr2 = new Array(3);console.log(arr1[0], arr2[0]);// undefined undefinedarr1.forEach(function(x){ console.log(x);})// undefined// undefined// undefinedarr2.forEach(function(x){ console.log(x);})// (无输出)
即显式的声明值为 undefined
并不表明这个值就是以前提到的空隙值,虽然两者经过索引访问时的值都返回 undefined
,可是其根本仍是有区别的,显式声明过的是能够被遍历等操做访问的,不会被当成空隙值被忽略;
拓展
一般在不少状况下,咱们想要直接声明一个数组并赋予其一些特定的初始值,而且为了不问题,一般是但愿申明为密集数组的,下面就介绍一些经常使用的方法或技巧:
var arr1 = new Array(3).fill(1);console.log(arr1);// [1, 1, 1]var arr2 = Array.fill().map((x, i) => i);console.log(arr2);// [0, 1, 2]var arr3 = Array.apply(null, Array(3));console.log(arr3);// [undefined, undefined, undefined]// 这样声明的是密集数组,不是稀疏的var arr4 = new Array(4).join('a').split('');console.log(arr4);// ['a', 'a', 'a']// 注意定义数组长度比输出数组大 1
其它更多的方法能够自行类推;
本文分享自微信公众号 - 程序骑士(program-knight)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。