JS數(shù)組循環(huán)的方式以及效率分析對(duì)比
數(shù)組的方法
JavaScript發(fā)展到現(xiàn)在已經(jīng)提供了許多數(shù)組的方法,下面這張圖涵蓋了數(shù)組大部分的方法,這篇文章主要說一說數(shù)組的遍歷方法,以及各自的性能,方法這么多,如何挑選性能最佳的方法對(duì)我們的開發(fā)有非常大的幫助。

數(shù)組遍歷的方法
for
- 標(biāo)準(zhǔn)的for循環(huán)語句,也是最傳統(tǒng)的循環(huán)語句
var arr = [1,2,3,4,5]
for(var i=0;i<arr.length;i++){
console.log(arr[i])
}
最簡(jiǎn)單的一種遍歷方式,也是使用頻率最高的,性能較好,但還能優(yōu)化
- 優(yōu)化版for循環(huán)語句
var arr = [1,2,3,4,5]
for(var i=0,len=arr.length;i<len;i++){
console.log(arr[i])
}
使用臨時(shí)變量,將長(zhǎng)度緩存起來,避免重復(fù)獲取數(shù)組長(zhǎng)度,尤其是當(dāng)數(shù)組長(zhǎng)度較大時(shí)優(yōu)化效果才會(huì)更加明顯。
這種方法基本上是所有循環(huán)遍歷方法中性能最高的一種
forEach
- 普通forEach
對(duì)數(shù)組中的每一元素運(yùn)行給定的函數(shù),沒有返回值,常用來遍歷元素
var arr5 = [10,20,30]
var result5 = arr5.forEach((item,index,arr)=>{
console.log(item)
})
console.log(result5)
/*
10
20
30
undefined 該方法沒有返回值
*/
數(shù)組自帶的foreach循環(huán),使用頻率較高,實(shí)際上性能比普通for循環(huán)弱
- 原型forEach
由于foreach是Array型自帶的,對(duì)于一些非這種類型的,無法直接使用(如NodeList),所以才有了這個(gè)變種,使用這個(gè)變種可以讓類似的數(shù)組擁有foreach功能。
const nodes = document.querySelectorAll('div')
Array.prototype.forEach.call(nodes,(item,index,arr)=>{
console.log(item)
})
實(shí)際性能要比普通foreach弱
for...in
任意順序遍歷一個(gè)對(duì)象的除Symbol以外的可枚舉屬性,包括繼承的可枚舉屬性。
一般常用來遍歷對(duì)象,包括非整數(shù)類型的名稱和繼承的那些原型鏈上面的屬性也能被遍歷。像 Array和 Object使用內(nèi)置構(gòu)造函數(shù)所創(chuàng)建的對(duì)象都會(huì)繼承自O(shè)bject.prototype和String.prototype的不可枚舉屬性就不能遍歷了.
var arr = [1,2,3,4,5]
for(var i in arr){
console.log(i,arr[i])
} //這里的i是對(duì)象屬性,也就是數(shù)組的下標(biāo)
/**
0 1
1 2
2 3
3 4
4 5 **/
大部分人都喜歡用這個(gè)方法,但它的性能卻不怎么好
for...of(不能遍歷對(duì)象)
在可迭代對(duì)象(具有 iterator 接口)(Array,Map,Set,String,arguments)上創(chuàng)建一個(gè)迭代循環(huán),調(diào)用自定義迭代鉤子,并為每個(gè)不同屬性的值執(zhí)行語句,不能遍歷對(duì)象
let arr=["前端","南玖","ssss"];
for (let item of arr){
console.log(item)
}
//前端 南玖 ssss
//遍歷對(duì)象
let person={name:"南玖",age:18,city:"上海"}
for (let item of person){
console.log(item)
}
// 我們發(fā)現(xiàn)它是不可以的 我們可以搭配Object.keys使用
for(let item of Object.keys(person)){
console.log(person[item])
}
// 南玖 18 上海
這種方式是es6里面用到的,性能要好于forin,但仍然比不上普通for循環(huán)
map
map: 只能遍歷數(shù)組,不能中斷,返回值是修改后的數(shù)組。
let arr=[1,2,3];
const res = arr.map(item=>{
return item+1
})
console.log(res) //[2,3,4]
console.log(arr) // [1,2,3]
every
對(duì)數(shù)組中的每一運(yùn)行給定的函數(shù),如果該函數(shù)對(duì)每一項(xiàng)都返回true,則該函數(shù)返回true
var arr = [10,30,25,64,18,3,9]
var result = arr.every((item,index,arr)=>{
return item>3
})
console.log(result) //false
some
對(duì)數(shù)組中的每一運(yùn)行給定的函數(shù),如果該函數(shù)有一項(xiàng)返回true,就返回true,所有項(xiàng)返回false才返回false
var arr2 = [10,20,32,45,36,94,75]
var result2 = arr2.some((item,index,arr)=>{
return item<10
})
console.log(result2) //false
reduce
reduce()方法對(duì)數(shù)組中的每個(gè)元素執(zhí)行一個(gè)由你提供的reducer函數(shù)(升序執(zhí)行),將其結(jié)果匯總為單個(gè)返回值
const array = [1,2,3,4] const reducer = (accumulator, currentValue) => accumulator + currentValue; // 1 + 2 + 3 + 4 console.log(array1.reduce(reducer));
filter
對(duì)數(shù)組中的每一運(yùn)行給定的函數(shù),會(huì)返回滿足該函數(shù)的項(xiàng)組成的數(shù)組
// filter 返回滿足要求的數(shù)組項(xiàng)組成的新數(shù)組
var arr3 = [3,6,7,12,20,64,35]
var result3 = arr3.filter((item,index,arr)=>{
return item > 3
})
console.log(result3) //[6,7,12,20,64,35]
性能測(cè)試工具測(cè)試
使用工具測(cè)試性能分析結(jié)果如下圖所示

手動(dòng)測(cè)試
我們也可以自己用代碼測(cè)試:
//測(cè)試函數(shù)
function clecTime(fn,fnName){
const start = new Date().getTime()
if(fn) fn()
const end = new Date().getTime()
console.log(`${fnName}執(zhí)行耗時(shí):${end-start}ms`)
}
function forfn(){
let a = []
for(var i=0;i<arr.length;i++){
// console.log(i)
a.push(arr[i])
}
}
clecTime(forfn, 'for') //for執(zhí)行耗時(shí):106ms
function forlenfn(){
let a = []
for(var i=0,len=arr.length;i<len;i++){
a.push(arr[i])
}
}
clecTime(forlenfn, 'for len') //for len執(zhí)行耗時(shí):95ms
function forEachfn(){
let a = []
arr.forEach(item=>{
a.push[item]
})
}
clecTime(forEachfn, 'forEach') //forEach執(zhí)行耗時(shí):201ms
function forinfn(){
let a = []
for(var i in arr){
a.push(arr[i])
}
}
clecTime(forinfn, 'forin') //forin執(zhí)行耗時(shí):2584ms (離譜)
function foroffn(){
let a = []
for(var i of arr){
a.push(i)
}
}
clecTime(foroffn, 'forof') //forof執(zhí)行耗時(shí):221ms
// ...其余可自行測(cè)試
結(jié)果分析
經(jīng)過工具與手動(dòng)測(cè)試發(fā)現(xiàn),結(jié)果基本一致,數(shù)組遍歷各個(gè)方法的速度:傳統(tǒng)的for循環(huán)最快,for-in最慢
for-len > for > for-of > forEach > map > for-in
javascript原生遍歷方法的建議用法:
- 用for循環(huán)遍歷數(shù)組
- 用for...in遍歷對(duì)象
- 用for...of遍歷類數(shù)組對(duì)象(ES6)
- 用Object.keys()獲取對(duì)象屬性名的集合
為何for… in會(huì)慢?
因?yàn)閒or … in語法是第一個(gè)能夠迭代對(duì)象鍵的JavaScript語句,循環(huán)對(duì)象鍵({})與在數(shù)組([])上進(jìn)行循環(huán)不同,引擎會(huì)執(zhí)行一些額外的工作來跟蹤已經(jīng)迭代的屬性。因此不建議使用for...in來遍歷數(shù)組
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript基礎(chǔ)進(jìn)階_深入剖析執(zhí)行環(huán)境及作用域鏈
下面小編就為大家?guī)硪黄猨avascript基礎(chǔ)進(jìn)階_深入剖析執(zhí)行環(huán)境及作用域鏈。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09
JavaScript實(shí)現(xiàn)的微信二維碼圖片生成器的示例
二維碼分享功能大多是由后端實(shí)現(xiàn)的,對(duì)服務(wù)器的負(fù)載較重,這里有一個(gè)前端實(shí)現(xiàn)的版本,本文介紹了JavaScript實(shí)現(xiàn)的微信二維碼圖片生成器的示例,有需要的可以了解一下。2016-10-10
javascript判斷元素存在和判斷元素存在于實(shí)時(shí)的dom中的方法
本文主要介紹了javascript判斷元素存在和判斷元素存在于實(shí)時(shí)的dom中的方法。具有一定的參考價(jià)值,下面跟著小編一起來看下吧2017-01-01
javascript動(dòng)態(tài)添加樣式(行內(nèi)式/嵌入式/外鏈?zhǔn)降纫?guī)則)
添加CSS的方式有行內(nèi)式、嵌入式、外鏈?zhǔn)?、?dǎo)入式,下面為大家詳細(xì)介紹下javascript動(dòng)態(tài)添加以上樣式規(guī)則的方法,感興趣的朋友可以參考下哈2013-06-06
微信小程序?qū)崿F(xiàn)點(diǎn)擊按鈕修改view標(biāo)簽背景顏色功能示例【附demo源碼下載】
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)點(diǎn)擊按鈕修改view標(biāo)簽背景顏色功能,涉及微信小程序事件響應(yīng)及數(shù)值運(yùn)算實(shí)現(xiàn)動(dòng)態(tài)設(shè)置view背景色樣式的相關(guān)操作技巧,需要的朋友可以參考下2017-12-12

