JS数组的几种遍历方法

2018-04-10  本文已影响0人  简森w

前言

最近感觉自己对数组遍历的方法有点混乱,for循环、forEach( )、map( )等方法混合使用,没有一个统一的规范,所以就打算总结一下。

ES5中的数组遍历方法

ES5为数组定义了5个迭代方法。每个方法都接受两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响 this 的值。
而传入的函数又可以接受三个参数:当前遍历的数组项的值,该项在数组中的位置和数组对象本身。

every( )

对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则every( )返回true。例如:

    let numbers = [1, 2, 3, 4];
    let everyResult = numbers.every((item, index, array)=>{
        return item > 1;
    })
    console.log(everyResult);  // 输出 false

filter( )

即对数组中的每一项运行给定函数,然后返回该函数会返回true的项。从名字就看得出来,这个方法是用来过滤数组项的,例如:

    let numbers = [1, 2, 3, 4];
    let filterResult = numbers.filter((item, index, array)=>{
        return item > 1;
    })
    console.log(filterResult);  // 输出 [2, 3, 4]

forEach( )

对数组的每一项运行给定函数。forEach方法是唯一一个没有返回值的,纯粹用来遍历数组。

    let numbers = [1, 2, 3, 4];
    numbers.forEach((item, index, array)=>{
        // 执行某些操作
    })

map( )

对数组的每一项运行给定函数,返回每次函数调用的返回值组成的数组。map方法就是有返回值的forEach方法,例如:

    let numbers = [1, 2, 3, 4];
    let mapResult = numbers.map((item, index, array)=>{
        return item * 2;
    })
    console.log(mapResult); // 输出 [2, 4, 6, 8]

some( )

对数组的每一项运行给定函数,如果该函数对任一项返回true,则some( )就返回true。some和every就像 ||&&,some是只要有一项满足,就返回true。

    let numbers = [1, 2, 3, 4];
    let someResult = numbers.some((item, index, array)=>{
        return item > 3;
    })
    console.log(someResult);  // 输出 true

ES5的这几个迭代方法,如果是只对item(当前遍历的数组项)进行操作,是不会改变原数组的,但是也可以通过给定函数中接收的index参数来改变原数组

除了ES5这几个方法,还有常见的简单for循环和ES6的for...of。

for...of

ES6借鉴了Java、Python等语言,引入了for...of循环。for...of主要用来统一ES6多种数据结构的遍历方法,不仅可以遍历数组,还可以遍历MapSet这两种ES6新推出的数据结构。只要具有iterator接口的数据结构,就可以用for...of循环来遍历。还可以遍历某些类似数组的对象,比如arguments对象、DOM NodeList 对象。

let numbers = [1, 2, 3, 4];
for(let item of numbers){
    console.log(item);
}
//输出
// 1
// 2
// 3
// 4

有关ES6新特性的内容,可以参考阮一峰老师的ES6入门教程

不推荐使用for...in来遍历数组,只用来遍历对象的属性

性能分析

这里主要测试一下for循环forEachfor...ofmapfor...in这几个方法遍历一个长度为100000的数组所耗费的时间。

//测试数据: arr = [1,2,3,4,...,99999,100000];

//普通for循环
console.time('普通for循环');
for(let i=0; i<arr.length; i++){

}
console.timeEnd('普通for循环')
//控制台输出 => 普通for循环: 0.923095703125ms


//forEach循环
console.time('forEach循环');
arr.forEach((item)=>{

})
console.timeEnd('forEach循环')
//控制台输出 => forEach循环: 1.973876953125ms


console.time('for...of循环');
for(let item of arr){

}
console.timeEnd('for...of循环')
//控制台输出 => for...of循环: 3.5810546875ms


//for...in循环
console.time('for...in循环');
for(let item in arr){
    
}
console.timeEnd('for...in循环')
//控制台输出 => for...in循环: 15.35693359375ms


//map循环循环
console.time('map循环');
arr.map((item) => {
    
})
console.timeEnd('map循环')
//控制台输出 => map循环: 19.4990234375ms

可能由于电脑配置等问题,这里你的控制台输出可能会不一样,甚至你刷新一下浏览器,两次的输出也会不一致。这里map( )居然比for...in的性能还低,印象中是for...in最低的,可能是因为测试的次数太少,有待研究。

总结

从性能上来说,for循环 > forEach > for...of > for...in > map,所以一般来说使用for循环是性能最高的,但是写法稍微复杂了点。但是性能好和要使用哪种遍历方法并没有太大关系,以现在的硬件水平来说,这里的性能差异完全可以忽略。所以一般来说,还需要考虑语义和功能需求。

如果你需要将数组按照给定规则转换并返回该结果数组,就使用map

如果你需要进行简单的遍历,用 forEach 或者 for of,但是 forEach 不能通过return和break语句来终止循环,所以如果需要中途终止循环,就使用 for...of或者 for循环

如果是在遍历数组的同时,需要改变原数组中的对应项,就用for循环

for...in会把数组所拥有可枚举的属性都遍历一次,所以可能会有意想不到的结果,不推荐用来遍历数组。

另外的三个,every( )filter( )some( )按功能需要来使用即可。

上一篇 下一篇

猜你喜欢

热点阅读