一乖订、概述:
在編程中,經(jīng)常需要對數(shù)據(jù)結(jié)構(gòu)進行遍歷沃于,在Javascript中它呀,從早期的Array、Object(泛指對Object的key的遍歷)洛勉,到ES6中的Set粘秆、Map的遍歷。
初學Javascript的同學收毫,最常用的便是使用for攻走、for in對數(shù)組、對象進行遍歷此再,但這兩種方法往往不是最佳的方案昔搂。本文將介紹本人所總結(jié)的比較常用、高效的遍歷方案输拇。
二摘符、數(shù)組的遍歷
1、for循環(huán)
var arr = [1,2,3,4];
for(var i=0, len=arr.length; i<len; i++){
console.log(arr[i])
}
這種遍歷的方式大家已經(jīng)十分熟悉策吠,在此不再贅述逛裤,僅作展示。
需要注意的便是如下涉及閉包的情況:
var arr = [1,2,3,4];
for(var i=0, len=arr.length; i<len; i++){
setTimeout(function(){
console.log(arr[i])
}, 20)
}
// output: undefined * 4 (即為 arr[4] 4次)
2猴抹、數(shù)組迭代方法
Javascript在ES5中带族,支持forEach、map蟀给、every蝙砌、some、filter迭代方法坤溃,這5種方法均為Array.prototype上的方法拍霜,分別有各自的應用場景,以下分別簡單介紹薪介,聲明數(shù)組arr并賦值:
var arr = [1,2,3,4,5];
Array.prototype.forEach :
詳細用法可參考:MDN文檔Array.prototype.forEach祠饺,本文僅作總結(jié):
代碼相比for更加簡潔,邏輯也較為清晰汁政,大部分場景下推薦使用forEach道偷。
// forEach
// 示例 1
arr.forEach(function(item, idx, arr){
console.log(item + '-' + idx) // output: 1-0 2-1 3-2 4-3 5-4
})
// 示例 2
arr.forEach(function(item){
setTimeout(function(){
console.log(item) // output: 1 2 3 4 5 ,可以避免for循環(huán)中出現(xiàn)的閉包問題
}, 20)
})
// 示例 3
var obj = {
name: 'Javascript'
}
arr.forEach(function(item){
console.log(this.name) // output: Javascript * 4
}, obj)
Array.prototype.map :
詳細用法可參考:MDN文檔Array.prototype.map记劈。
map與forEach的遍歷方式一致勺鸦,區(qū)別在于map中會將每次迭代函數(shù)執(zhí)行結(jié)果組成一個新的數(shù)組返回,如下:
var newArr = arr.map(function(item){
return item * 2
})
console.log(newArr) // output: [2, 4, 6, 8, 10]
// ES6 寫法
var newArr2 = arr.map(item => item*2)
map遵循函數(shù)式編程的原則目木,不對原數(shù)組作修改换途,僅返回新數(shù)組,是十分常用的數(shù)組遞歸方法,而且在性能測試中军拟,微微領(lǐng)先于for剃执、forEach(實際差別不大,可以忽略)懈息。
forEach適用的范圍肾档,map均可以勝任,所以辫继,可以看到在開源項目中怒见,大量使用map替代forEach來進行迭代。
此外姑宽,由于map返回Array對象遣耍,因此,可以實現(xiàn)鏈式調(diào)用低千。
Array.prototype.filter :
詳細用法可參考:MDN文檔Array.prototype.filter配阵。
filter用于篩選出數(shù)組中符合條件的元素,并組成新的數(shù)組示血,如下:
var filtered = arr.filter(function(item){
return item>3
})
console.log(filtered) // output: [4, 5]
Array.prototype.some :
詳細用法可參考:MDN文檔Array.prototype.some。
some判斷數(shù)組中至少有一項元素滿足指定條件救拉,如下:
var isHas = arr.some(function(item){
return item>3
})
console.log(isHas) // output: true
Array.prototype.every :
詳細用法可參考:MDN文檔Array.prototype.every难审。
every用以判斷數(shù)組是否每一項均滿足條件,如有一項不滿足亿絮,則跳出循環(huán):
var isEvery = arr.every(function(item){
return item<4
})
console.log(isEvery) // output: false
總結(jié):
- 在對數(shù)組進行遍歷的時候告喊,如果只需依次遍歷每個元素,可使用forEach或map方法派昧;
- 需要將每一項處理結(jié)果返回的黔姜,可使用map方法;
- 判斷是否每一項均符合條件時蒂萎,使用every秆吵;
- 判斷是否至少有一項滿足條件,使用some五慈;
- 需要篩選出符合條件的所有項組成數(shù)組纳寂,使用filter;
- map泻拦、filter可以實現(xiàn)鏈式調(diào)用毙芜。
3、for...of 與 迭代器(ES6)
在ES6中争拐,新增了迭代器對象腋粥,可以通過迭代器對數(shù)組進行迭代,例如以下代碼:
var arr = ['a','b','c','d','e'];
for(var value of arr){
console.log(value) // output: 'a' 'b' 'c' 'd' 'e'
}
for(var key of arr.keys()){
console.log(key) // output: 0 1 2 3 4
}
for(var each of arr.entries()){
console.log(each)
// output: [0, 'a'], [1, 'b'], [2, 'c'], [3, 'd'], [4, 'e'] 即:[key, value]
}
具體用法可參考:MDN文檔for...of迭代
數(shù)組對象默認使用值作為迭代的值,開發(fā)者可根據(jù)需要隘冲,使用keys金赦、 entries分別返回數(shù)組的鍵、鍵值對作為值的迭代對象对嚼。
使用for...of語句夹抗,可以減少大量的代碼量,并且邏輯清晰纵竖,使用方法靈活漠烧,在支持ES6的環(huán)境中,強烈推薦使用靡砌。