前言
最近感覺(jué)自己對(duì)數(shù)組遍歷的方法有點(diǎn)混亂荡澎,for循環(huán)蕊程、forEach( )雏搂、map( )等方法混合使用藕施,沒(méi)有一個(gè)統(tǒng)一的規(guī)范,所以就打算總結(jié)一下凸郑。
ES5中的數(shù)組遍歷方法
ES5為數(shù)組定義了5個(gè)迭代方法裳食。每個(gè)方法都接受兩個(gè)參數(shù):要在每一項(xiàng)上運(yùn)行的函數(shù)和(可選的)運(yùn)行該函數(shù)的作用域?qū)ο蟆绊?
this
的值。
而傳入的函數(shù)又可以接受三個(gè)參數(shù):當(dāng)前遍歷的數(shù)組項(xiàng)的值芙沥,該項(xiàng)在數(shù)組中的位置和數(shù)組對(duì)象本身诲祸。
every( )
對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)浊吏,如果該函數(shù)對(duì)每一項(xiàng)都返回true,則every( )返回true救氯。例如:
let numbers = [1, 2, 3, 4];
let everyResult = numbers.every((item, index, array)=>{
return item > 1;
})
console.log(everyResult); // 輸出 false
filter( )
即對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)找田,然后返回該函數(shù)會(huì)返回true的項(xiàng)。從名字就看得出來(lái)着憨,這個(gè)方法是用來(lái)過(guò)濾數(shù)組項(xiàng)的墩衙,例如:
let numbers = [1, 2, 3, 4];
let filterResult = numbers.filter((item, index, array)=>{
return item > 1;
})
console.log(filterResult); // 輸出 [2, 3, 4]
forEach( )
對(duì)數(shù)組的每一項(xiàng)運(yùn)行給定函數(shù)。forEach方法是唯一一個(gè)沒(méi)有返回值的甲抖,純粹用來(lái)遍歷數(shù)組漆改。
let numbers = [1, 2, 3, 4];
numbers.forEach((item, index, array)=>{
// 執(zhí)行某些操作
})
map( )
對(duì)數(shù)組的每一項(xiàng)運(yùn)行給定函數(shù),返回每次函數(shù)調(diào)用的返回值組成的數(shù)組准谚。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( )
對(duì)數(shù)組的每一項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對(duì)任一項(xiàng)返回true柱衔,則some( )就返回true暮顺。some和every就像 ||
和 &&
,some是只要有一項(xiàng)滿足秀存,就返回true捶码。
let numbers = [1, 2, 3, 4];
let someResult = numbers.some((item, index, array)=>{
return item > 3;
})
console.log(someResult); // 輸出 true
ES5的這幾個(gè)迭代方法,如果是只對(duì)item
(當(dāng)前遍歷的數(shù)組項(xiàng))進(jìn)行操作或链,是不會(huì)改變?cè)瓟?shù)組的惫恼,但是也可以通過(guò)給定函數(shù)中接收的index
參數(shù)來(lái)改變?cè)瓟?shù)組
除了ES5這幾個(gè)方法,還有常見(jiàn)的簡(jiǎn)單for循環(huán)和ES6的for...of澳盐。
for...of
ES6借鑒了Java祈纯、Python等語(yǔ)言,引入了for...of
循環(huán)叼耙。for...of
主要用來(lái)統(tǒng)一ES6多種數(shù)據(jù)結(jié)構(gòu)的遍歷方法腕窥,不僅可以遍歷數(shù)組,還可以遍歷Map
筛婉、Set
這兩種ES6新推出的數(shù)據(jù)結(jié)構(gòu)簇爆。只要具有iterator
接口的數(shù)據(jù)結(jié)構(gòu),就可以用for...of循環(huán)來(lái)遍歷爽撒。還可以遍歷某些類似數(shù)組的對(duì)象入蛆,比如arguments對(duì)象、DOM NodeList 對(duì)象硕勿。
let numbers = [1, 2, 3, 4];
for(let item of numbers){
console.log(item);
}
//輸出
// 1
// 2
// 3
// 4
有關(guān)ES6新特性的內(nèi)容哨毁,可以參考阮一峰老師的ES6入門教程
不推薦使用for...in
來(lái)遍歷數(shù)組,只用來(lái)遍歷對(duì)象的屬性源武。
性能分析
這里主要測(cè)試一下for循環(huán)
扼褪、forEach
想幻、for...of
、map
话浇、for...in
這幾個(gè)方法遍歷一個(gè)長(zhǎng)度為100000的數(shù)組所耗費(fèi)的時(shí)間脏毯。
//測(cè)試數(shù)據(jù): arr = [1,2,3,4,...,99999,100000];
//普通for循環(huán)
console.time('普通for循環(huán)');
for(let i=0; i<arr.length; i++){
}
console.timeEnd('普通for循環(huán)')
//控制臺(tái)輸出 => 普通for循環(huán): 0.923095703125ms
//forEach循環(huán)
console.time('forEach循環(huán)');
arr.forEach((item)=>{
})
console.timeEnd('forEach循環(huán)')
//控制臺(tái)輸出 => forEach循環(huán): 1.973876953125ms
console.time('for...of循環(huán)');
for(let item of arr){
}
console.timeEnd('for...of循環(huán)')
//控制臺(tái)輸出 => for...of循環(huán): 3.5810546875ms
//for...in循環(huán)
console.time('for...in循環(huán)');
for(let item in arr){
}
console.timeEnd('for...in循環(huán)')
//控制臺(tái)輸出 => for...in循環(huán): 15.35693359375ms
//map循環(huán)循環(huán)
console.time('map循環(huán)');
arr.map((item) => {
})
console.timeEnd('map循環(huán)')
//控制臺(tái)輸出 => map循環(huán): 19.4990234375ms
可能由于電腦配置等問(wèn)題,這里你的控制臺(tái)輸出可能會(huì)不一樣凳枝,甚至你刷新一下瀏覽器抄沮,兩次的輸出也會(huì)不一致。這里map( )
居然比for...in
的性能還低岖瑰,印象中是for...in
最低的叛买,可能是因?yàn)闇y(cè)試的次數(shù)太少,有待研究蹋订。
總結(jié)
從性能上來(lái)說(shuō)率挣,for循環(huán)
> forEach
> for...of
> for...in
> map
,所以一般來(lái)說(shuō)使用for循環(huán)
是性能最高的露戒,但是寫法稍微復(fù)雜了點(diǎn)椒功。但是性能好和要使用哪種遍歷方法并沒(méi)有太大關(guān)系,以現(xiàn)在的硬件水平來(lái)說(shuō)智什,這里的性能差異完全可以忽略动漾。所以一般來(lái)說(shuō),還需要考慮語(yǔ)義和功能需求荠锭。
如果你需要將數(shù)組按照給定規(guī)則轉(zhuǎn)換并返回該結(jié)果數(shù)組旱眯,就使用map
。
如果你需要進(jìn)行簡(jiǎn)單的遍歷证九,用 forEach
或者 for of
删豺,但是 forEach
不能通過(guò)return和break語(yǔ)句來(lái)終止循環(huán),所以如果需要中途終止循環(huán)愧怜,就使用 for...of
或者 for循環(huán)
呀页。
如果是在遍歷數(shù)組的同時(shí),需要改變?cè)瓟?shù)組中的對(duì)應(yīng)項(xiàng)拥坛,就用for循環(huán)
蓬蝶。
for...in
會(huì)把數(shù)組所擁有可枚舉的屬性都遍歷一次,所以可能會(huì)有意想不到的結(jié)果渴逻,不推薦用來(lái)遍歷數(shù)組疾党。
另外的三個(gè),every( )
惨奕、filter( )
、some( )
按功能需要來(lái)使用即可竭钝。