原文首發至 fe2x.cc 轉載請標註原做者和附帶原文鏈接javascript
JavaScript 發展至今已經發展出多種數組的循環遍歷的方法,不一樣的遍歷方法運行起來那個比較快,不一樣循環方法使用在那些場景,下面將進行比較:html
for
語句代碼:java
var arr = [1,2,4,6]
for(var i = 0, len = arr.length; i < len; i++){
console.log(arr[i])
}
複製代碼
這是標準for循環的寫法也是最傳統的語句,字符串也支持,定義一個變量i做爲索引,以跟蹤訪問的位置,len是數組的長度,條件就是i不能超過len。git
forEach
語句forEach
方法對數組的每一個元素執行一次提供的CALLBACK函數,forEach是一個數組方法,能夠用來把一個函數套用在一個數組中的每一個元素上,forEach
爲每一個數組元素執行callback函數只可用於數組.遍歷一個數組讓數組每一個元素作一件事情.那些已刪除(使用delete方法等狀況)或者未初始化的項將被跳過(但不包括那些值爲 undefined 的項)(例如在稀疏數組上);不像map() 或者reduce() ,它老是返回 undefined值,而且不可鏈式調用。典型用例是在一個鏈的最後執行反作用。es6
代碼:github
var arr = [1,5,8,9]
arr.forEach(function(item) {
console.log(item);
})
複製代碼
for-in
語句通常會使用for-in
來遍歷對象的屬性的,不過屬性須要 enumerable
,才能被讀取到. for-in
循環只遍歷可枚舉屬性。通常經常使用來遍歷對象,包括非整數類型的名稱和繼承的那些原型鏈上面的屬性也能被遍歷。像 Array和 Object使用內置構造函數所建立的對象都會繼承自Object.prototype和String.prototype的不可枚舉屬性就不能遍歷了.數組
代碼:瀏覽器
var obj = {
name: 'test',
color: 'red',
day: 'sunday',
number: 5
}
for (var key in obj) {
console.log(obj[key])
}
複製代碼
for-of
語句 (ES 6)for-of
語句在可迭代對象(包括 Array,Map,Set,String,TypedArray,arguments 對象等等)上建立一個迭代循環,調用自定義迭代鉤子,併爲每一個不一樣屬性的值執行語句。只要是一個iterable的對象,就能夠經過for-of
來迭代.jsp
代碼:編輯器
var arr = [{name:'bb'},5,'test']
for (item of arr) {
console.log(item)
}
複製代碼
for-of
和 for-in
的區別for-in
語句以原始插入順序迭代對象的可枚舉屬性。for-in
會把繼承鏈的對象屬性都會遍歷一遍,因此會更花時間.
for-of
語句只遍歷可迭代對象的數據。
map
方法 (不改變原數組)map
方法會給原數組中的每一個元素都按順序調用一次 callback 函數。callback 每次執行後的返回值(包括 undefined)組合起來造成一個新數組。 callback 函數只會在有值的索引上被調用;那些歷來沒被賦過值或者使用 delete 刪除的索引則不會被調用。讓數組經過某種計算產生一個新數組,影射成一個新的數組,
代碼:
var arr = [1,2,3]
var firearr = arr.map(current => current * 5)
複製代碼
reduce
方法讓數組中的前項和後項作某種計算,並累計最終值,
代碼:
var wallets = [4,7.8,3]
var totalMoney = wallets.reduce( function (countedMoney, wallet) {
return countedMoney + wallet.money;
}, 0)
複製代碼
filter
方法 (不改變原數組)filter
爲數組中的每一個元素調用一次 callback 函數,並利用全部使得 callback 返回 true 或 等價於 true 的值 的元素建立一個新數組。callback 只會在已經賦值的索引上被調用,對於那些已經被刪除或者從未被賦值的索引不會被調用。那些沒有經過 callback 測試的元素會被跳過,不會被包含在新數組中。篩選出過濾出數組中符合條件的項,組成新數組.
代碼:
var arr = [2,3,4,5,6]
var morearr = arr.filter(function (number) {
return number > 3
})
複製代碼
every
方法every 方法爲數組中的每一個元素執行一次 callback 函數,直到它找到一個使 callback 返回 false(表示可轉換爲布爾值 false 的值)的元素。若是發現了一個這樣的元素,every 方法將會當即返回 false。不然,callback 爲每個元素返回 true,every 就會返回 true。檢測數組中的每一項是否符合條件,若是每一項都符合條件,就會返回true,不然返回false,有點像遍歷數組且操做callback。只會爲那些已經被賦值的索引調用。不會爲那些被刪除或歷來沒被賦值的索引調用。
代碼:
var arr = [1,2,3,4,5]
var result = arr.every(function (item, index) {
return item > 0
})
複製代碼
some
方法some 爲數組中的每個元素執行一次 callback 函數,直到找到一個使得 callback 返回一個「真值」(便可轉換爲布爾值 true 的值)。若是找到了這樣一個值,some 將會當即返回 true。不然,some 返回 false。callback 只會在那些」有值「的索引上被調用,不會在那些被刪除或歷來未被賦值的索引上調用。檢查數組中是否有某些項符號條件,若是有一項就返回true,不然返回false,有點像遍歷數組或者操做.
代碼:
var arr = [1,2,3,4,5]
var result = arr.some(function (item,index) {
return item > 3
})
複製代碼
對比這裏我使用了jsPerf平臺進行測試.
我建立了兩個數組進行對比,爲何要這樣區別呢,由於不一樣類型的數組在javascript內存中保存的地址格式不同,遍歷的時候編輯器會根椐數組元素的類型長度計算,好比說若是數組裏面全是Number類的,循環起來會比數組裏麪包含Number,String,Object混合型的會快,因此建立了兩個數組,一個是全undefined數組,一個是混合型數組.
// 一個是空數組
var nullarr = new Array(10000) // [undefined,undefined,...undefined]
// 另外一個帶不一樣類型的數據的數組
var dataarr = []
for(var i = 0; i < 10000; i++){
if (i % 2 ===0) {
dataarr[i] = i.toString()
} else {
dataarr[i = i
}
}
dataarr // [1,'2',3...,10000]
複製代碼
測試後發現有點奇怪直接檢索空數組仍是會比數據數組慢這是爲何呢奇怪?爲了對比循環的一致性我只選其中帶數據的數組dataarr
進行測試.
那咱們對比一下 for
for len
forEach
for-in
for-of
map
filter
循環的速度
能夠看到 for
循環的速度是最快的,是最老的循環,也是優化得最好的,其次是for-of
這個是es6才新增的循環很是好用,最慢是for-in
咱們能夠做一下速度排序
for
>for-of
>forEach
>filter
>map
>for-in
這很明顯處理大量循環數據的時候仍是要使用古老for
循環效率最好,但也不是不使用for-in
,其實不少時候都要根據實際應該場景的,for-in
更多使用在遍歷對象屬性上面,for-in
在遍歷的過程當中還會遍歷繼承鏈,因此這就是它效率比較慢的緣由,好比map
速率不高,不過處理在Es6實現數組功能上面很是好用方便,輕鬆影射建立新數組.或者例如使用Iterator屬性也是行的,因此每一個循環都有合適使用的地方.
every
和 some
不徹底屬於數組操做方法every
和 some
都是判斷條件直接返回整個數組Boolean類型的方法.every
速度會比some
快不少.
一張圖展現JavaScript數組方法
最後不一樣瀏覽器內核我相信會有些許差異,有興趣的朋友能夠去測試一下,有任何問題歡迎給博主留言.
附上測試的 地址