今天做项目时,遇到了一个很大很大的数组,并且需要在数组中去实现模糊搜索。因为现在数据时代,数据繁多,平时进行数据可视化开发时,经常遇到针对数组的排序、遍历、搜索、增删、去重等等操作。所以在这里就想着写一篇有关js数组循环的讨论。(以后应该会补充有关对象迭代的问题)
其实现在js循环方法已经有许多,从最初的for、while
到后来es6中的foreach、for in、for of、map、filter
,以及还有不常用的reduce、every
和some
方法。其实不同的方法使用场景不同,比如for in
遍历键值,for of
遍历值(其实虽然for in
经常用于遍历对象,但下文还是主要针对于数组比较),所以其实不能够盲目去比较。但是当一个场景,你找不到最适用的方法,其实就可以从本文找找思路,本文也就最简单的循环进行遍历的效率与性能的测试,希望能得到一个适用普通场景最佳循环方法的结论。
var arr = [1, 2, 3, ..., 9999999] // 这里创建数组的步骤就省略
// method 1
for(let i = 0; i < arr.length; i++) { console.log(arr[i]) }
// method 2
for(let i = 0, len = arr.length; i < len; i++) { console.log(arr[i]) }
// method 3
for(let i = 0, arrIndex; arrIndex = arr[i]; i++) { console.log(arrIndex) }
对于上面三种方法,前两种比较常见,对于方法一和方法二,其实很多人更愿意用第一种方法,因为不需要多声明一个len
变量,但是其实相对于大一点的数组,可以使用方法二,先将数组的长度缓存到一个变量len
种,循环就不需要每次都去执行arr.length
这一个方法了。对于第三种方法其实是将取值与判断进行合并,然后不停枚举直到为空。
对于三种循环方式,我们使用将每一个数字push
到一个新的数组中(可以理解为进行一个简单的操作,适当增大时间,从而可以看出对比差距),通过console.time
和console.timeEnd
的差值来判断执行效率。
先上比较代码
var arr = [] // 这里创建数组的步骤就省略
for(let j = 1; j <= 9999999; j++) {
arr.push(j);
}
function method1() {
var arr1 = [];
console.time('方法1')
for(let i = 0; i < arr.length; i++) {
arr1.push(arr[i]);
}
console.timeEnd('方法1')
}
function method2() {
var arr2 = [];
console.time('方法2')
for(let i = 0, len = arr.length; i < len; i++) {
arr2.push(arr[i]);
}
console.timeEnd('方法2')
}
function method3() {
var arr3 =[];
console.time('方法3')
for(let i = 0, arrValue; arrValue = arr[i]; i++) {
arr3.push(arrValue)
}
console.timeEnd('方法3')
}
method1();
method2();
method3();
Alt text
测试多次其实可以得到一个结论,数据很多时,最常见for
循环的写法,不再是最优,可以看出它与方法二三都有一定的差距。
像for in
这种用于遍历对象的就不示例了,实用性不大,所以就列出以下几种方法的使用,与效率代码(forEach、 map、 for of
)
还是照样付代码和结论:
function method4() {
var arr4 = []
console.time('方法4')
arr.forEach((item) => {
arr4.push(item)
})
console.timeEnd('方法4')
}
function method5() {
var arr5 = []
console.time('方法5')
arr5 = arr.map(item => item)
console.timeEnd('方法5')
}
function method6() {
var arr6 = []
console.time('方法6')
for (let item of arr) {
arr6.push(item)
}
console.timeEnd('方法6')
}
method1();
method2();
method3();
method4();
method5();
method6();
时间比较(单位ms同时省略小数点后面的数字)
方法一 | 方法二 | 方法三 | 方法四 | 方法五 | 方法六 |
---|---|---|---|---|---|
314 | 279 | 290 | 412 | 198 | 424 |
323 | 288 | 283 | 428 | 207 | 1171 |
352 | 294 | 288 | 414 | 196 | 442 |
286 | 284 | 295 | 445 | 194 | 378 |
由上表可以看出,forEach
和for of
方法比传统的for
循环效率效率更低,但map
确实出乎意料的高效率,我想了想,可能是因为map
有一个返回值,所以说它无需重新调用push
方法,所以有一定优势。
但是虽然说forEach
和for of
效率相对较低,甚至图表中出现了不稳定的现象,但是终究这些es6的方法有方便之处,比如for of
直接对每个数值进行遍历,而省去了使用arr[index]
这种步骤。
但是根据网上的说法,不同浏览器它们对于不同方法响应不同,于是默默打开safari,比较了一下...(乱码咱就不care了)
Alt text
Alt text
果不其然,ios对开发的支持效果是真的好。(难怪开发都喜欢用mac哈哈哈)
还是回归到原来,但从简单业务上来讲,for
循环可谓是简单高效,但是网上经常言传es6高效循环等等,实际是我觉得可能是在说针对某一业务场景,使用es6的便利性更高,代码更简洁吧(这里并不是指狭义的运行时间,还要考虑开发成本,比如重复赘余的写arr[i]
这种)。并且最后一点告诉我们,浏览器也很重要,这对各大浏览器制造商也是一个极大的考验,毕竟这个时间差对于用户体验来讲,还是值得去最小化的~