簡(jiǎn)單了解JS中的幾種遍歷

忙了好一段時(shí)間删掀,項(xiàng)目上線后終于有那么一點(diǎn)點(diǎn)空檔期靜下來(lái)整理一些問(wèn)題了姻檀。當(dāng)我們?cè)陂_(kāi)發(fā)項(xiàng)目的時(shí)候,用到遍歷的地方肯定少不了人断,那么我們有那么多的遍歷方法,在不同情況下用那種方法會(huì)更優(yōu)雅而且還沒(méi)bug呢搀暑?

首先蚂四,我在這里先列出幾種常見(jiàn)的遍歷機(jī)制光戈,然后針對(duì)部分來(lái)做一個(gè)我對(duì)它的理解,有不同看法的老鐵也可以分享一下遂赠,下面是我列出來(lái)的幾種遍歷的方法久妆,另外我們常用來(lái)中斷循環(huán)的語(yǔ)句我在這里簡(jiǎn)單的提一下:

a、continue: 中斷本次循環(huán)跷睦;

b筷弦、return和break直接跳出循環(huán)。

var arr = [1, 2, 3] for(var i = 0; i < arr.length; i++) { 
    //do something
}; 
// for...of...
for(var i of arr) { 
    //do something
}; 
// for...in..
for(var i in arr) { 
    //do something
}; 
// forEach()
arr.forEach((item, index, arr) => { 
    //do something});
});

// map()
arr.map((value,index,array) => {
    //do something
});

在開(kāi)發(fā)上一個(gè)項(xiàng)目的時(shí)候抑诸,我在用for...in...這個(gè)方法遍歷的時(shí)候就遇到一個(gè)詭異的bug烂琴,在android手機(jī)是完美的展示,但是在iPhone手機(jī)的時(shí)候蜕乡,就出現(xiàn)了遍歷后的數(shù)據(jù)竟然是翻倍的奸绷,而且數(shù)據(jù)是重復(fù)的。然后我就想著用array.forEach的方法异希,來(lái)解決問(wèn)題總該行來(lái)吧健盒,在正常邏輯的情況下是可以解決問(wèn)題的,但是称簿,在稍微復(fù)雜的邏輯了扣癣,有時(shí)候我們要中斷forEach遍歷時(shí),這時(shí)候就會(huì)顯得軟弱無(wú)力了憨降,因?yàn)樵趂orEach的遍歷機(jī)制里是不支持中斷遍歷的父虑,然后我只能尋求其他的解決方案了。

下面我在這對(duì)上述列舉的遍歷方法逐個(gè)逐個(gè)的分析一下授药,有些分析不到位的士嚎,或者有不同的看法的老鐵們請(qǐng)分享你的看法:

1. 普通的for循環(huán)

var arr = [1, 2, 3] for(var i = 0; i < arr.length; i++) { // 這里的i是代表數(shù)組的下標(biāo)
    console.log(i); // 0, 1, 2
};

最簡(jiǎn)單的一種,正常用的話也不會(huì)出現(xiàn)什么問(wèn)題悔叽,想中斷也可以中斷莱衩,性能上也還可以。

image

2. 優(yōu)化版的for循環(huán)

var arr = [1, 2, 3] ;
for(var i = 0, len = arr.length; i < len; i++) { // 這里的i是代表數(shù)組的下標(biāo)
    console.log(i); // 0, 1, 2 
};

使用臨時(shí)變量娇澎,將長(zhǎng)度緩存起來(lái)笨蚁,避免重復(fù)獲取數(shù)組長(zhǎng)度,當(dāng)數(shù)組較大時(shí)優(yōu)化效果才會(huì)比較明顯。這種方法基本上是所有循環(huán)遍歷方法中性能最高的一種括细,并且這一類型的for循環(huán)可以通過(guò)用break來(lái)中斷循環(huán)伪很,如下圖所示:

image

3. for...of...遍歷(這種遍歷支持ES6)

var arr = [1, 2, 3] ;
for(var item of arr) { // item代表數(shù)組里面的元素
    console.log(item); // 1, 2, 3
};

1、 這是最簡(jiǎn)潔奋单、最直接的遍歷數(shù)組元素的語(yǔ)法

2锉试、 這個(gè)方法避開(kāi)了for-in循環(huán)的所有缺陷

3、 與forEach()不同的是览濒,它可以正確響應(yīng)break呆盖、continue和return語(yǔ)句

4、性能要好于forin贷笛,但仍然比不上普通for循環(huán)

image

4. forEach()

var arr = [1, 2, 3];
arr.forEach((item, index, arr) => { // item為arr的元素絮短,index為下標(biāo),arr原數(shù)組
    console.log(item); // 1, 2, 3
    console.log(index); // 0, 1, 2
    console.log(arr); // [1, 2, 3]
});

這種遍歷便捷還是挺便捷的昨忆,看起來(lái)優(yōu)雅丁频,對(duì)目標(biāo)數(shù)組的操作很人性化,要元素給元素邑贴,要下標(biāo)給下標(biāo)席里,但是當(dāng)某種情況你想中斷遍歷的時(shí)候,你就會(huì)感覺(jué)它就像雞肋拢驾,食之無(wú)味奖磁,棄之可惜。由于foreach是Array型自帶的繁疤,對(duì)于一些非這種類型的咖为,無(wú)法直接使用(如NodeList),所以才有了這個(gè)變種稠腊,使用這個(gè)變種可以讓類似的數(shù)組擁有foreach功能躁染。而且forEach的性能也會(huì)比普通的for循環(huán)弱。又下面的例子我們可以看到架忌,我們常用的return false是可以終止代碼繼續(xù)往下執(zhí)行的吞彤,但是在forEach遍歷中,并沒(méi)有終止循環(huán)叹放,所以在用forEach的時(shí)候饰恕,要考慮使用場(chǎng)景了。

image

5.some()

var arr = [1, 2, 3];
arr.some((item, index, arr) => { // item為數(shù)組中的元素井仰,index為下標(biāo)埋嵌,arr為目標(biāo)數(shù)組
    console.log(item); // 1, 2, 3
    console.log(index); // 0, 1, 2
    console.log(arr); // [1, 2, 3] 
});

some作為一個(gè)用來(lái)檢測(cè)數(shù)組是否滿足一些條件的函數(shù)存在,同樣是可以用作遍歷的函數(shù)簽名同forEach俱恶,有區(qū)別的是當(dāng)任一callback返回值匹配為true則會(huì)直接返回true雹嗦,如果所有的callback匹配均為false拌喉,則返回false。

some() 方法會(huì)依次執(zhí)行數(shù)組的每個(gè)元素:

  • 如果有一個(gè)元素滿足條件俐银,則表達(dá)式返回true , 剩余的元素不會(huì)再執(zhí)行檢測(cè)。
  • 如果沒(méi)有滿足條件的元素端仰,則返回false捶惜。
image

7. every()

var arr = [1, 2, 3];
arr.every((item, index, arr) => { // item為數(shù)組中的元素,index為下標(biāo)荔烧,arr為目標(biāo)數(shù)組
    return item > 0; // true
    return index == 0; // false
});

every() 方法用于檢測(cè)數(shù)組所有元素是否都符合指定條件(通過(guò)函數(shù)提供)吱七。

every() 方法使用指定函數(shù)檢測(cè)數(shù)組中的所有元素:

  • 如果數(shù)組中檢測(cè)到有一個(gè)元素不滿足,則整個(gè)表達(dá)式返回 false 鹤竭,且剩余的元素不會(huì)再進(jìn)行檢測(cè)踊餐。
  • 如果所有元素都滿足條件,則返回 true臀稚。
image

8. for...in...遍歷

var arr = [1, 2, 3] for(var item in arr) { // item遍歷數(shù)組時(shí)為數(shù)組的下標(biāo)吝岭,遍歷對(duì)象時(shí)為對(duì)象的key值
    console.log(item); // 0, 1, 2
};

for...in更多是用來(lái)遍歷對(duì)象,很少用來(lái)遍歷數(shù)組吧寺, 不過(guò) item 對(duì)應(yīng)與數(shù)組的 key值窜管,建議不要用該方法來(lái)遍歷數(shù)組,因?yàn)樗男适亲畹偷摹?/p>

image

9. filter()

var arr = [1, 2, 3];
arr.filter(item => { // item為數(shù)組當(dāng)前的元素
    return item > 1; // [2, 3]
});

filter() 方法創(chuàng)建一個(gè)新的數(shù)組稚机,新數(shù)組中的元素是通過(guò)檢查指定數(shù)組中符合條件的所有元素幕帆。

image

10. map()

var arr = [1, 2, 3];
arr.map(item => { // item為數(shù)組的元素
    console.log(item); // 1, 2, 3
    return item * 2; // 返回一個(gè)處理過(guò)的新數(shù)組[2, 4, 6]
});

map() 方法返回一個(gè)新數(shù)組,數(shù)組中的元素為原始數(shù)組元素調(diào)用函數(shù)處理后的值赖条。

map() 方法按照原始數(shù)組元素順序依次處理元素失乾。

這種方式也是用的比較廣泛的,雖然用起來(lái)比較優(yōu)雅纬乍,但實(shí)際效率還比不上foreach

image

上述簡(jiǎn)單的介紹了各種遍歷的方法碱茁。

在前面我有提到一個(gè)蘋果手機(jī)遍歷出現(xiàn)數(shù)據(jù)重復(fù)的bug,那么我在這里做一個(gè)用for...in...案例仿贬,首先來(lái)看看代碼:

for (let item in this.currentForm) {
  var subFormDataObj = {}; if (this.currentForm[item].isRequired === 2 && !this.currentForm[item].subjectValue && this.currentForm[item].subjectType != 5) { this.isSubmit = true; this.hideLoading(); this.Toast('尚有數(shù)據(jù)未完成早芭,提交失敗诅蝶!'); return false;
   } else { if (this.expressionTest(this.currentForm[item].subjectValue)) { this.Toast('內(nèi)容不能含有表情符退个,請(qǐng)重新輸入!'); this.isSubmit = true; this.hideLoading(); return false;
       } if (this.currentForm[item].subjectName.indexOf('手機(jī)號(hào)') > -1) { if(!this.checkPhone(this.currentForm[item].subjectValue)) { this.isSubmit = true; this.hideLoading(); return false;
           };
       }
       subFormDataObj.subjectId = this.currentForm[item].subjectId;
       subFormDataObj.subjectValue = this.currentForm[item].subjectValue;
       subFormDataObj.picture = this.currentForm[item].picurl;
       subFormDataObj.isRequired = this.currentForm[item].isRequired; if (this.currentForm[item].subjectType == 5) { if (this.listPicStr == '') { this.isSubmit = true; this.hideLoading(); this.Toast('尚有數(shù)據(jù)未完成调炬,提交失斢镉!'); return false;
           } else { // subFormDataObj.picture = "data:image/jpeg;base64," + this.listPicStr.replace(/data:image\/jpeg;base64,/g,'') || '';
 }
       }
       subFormData.push(subFormDataObj);
   }
};
alert(JSON.stringify(subFormData));
image
image

我們看一下安卓手機(jī)和蘋果手機(jī)alert出來(lái)的數(shù)據(jù)有什么區(qū)別:在截圖中我們就可以發(fā)現(xiàn)缰泡,蘋果手機(jī)整體遍歷了2輪刀荒,這樣個(gè)結(jié)果是不是很詭異代嗤?是的我也覺(jué)得很詭異,怎么來(lái)解決呢缠借,很多很學(xué)會(huì)想到一些方法干毅,比如用數(shù)組去重的方法,并且es6的去重方法很優(yōu)雅(var newArr = Array.from(new Set(subFormData)))泼返,或者其他去重的方法硝逢,這樣做并沒(méi)有什么不好,比較方法有千千萬(wàn)绅喉,喜歡就好渠鸽。當(dāng)時(shí)因?yàn)榭紤]到里面的邏輯問(wèn)題,我就直接改了一行代碼柴罐,用了最普通的方法徽缚,因?yàn)樾阅苌蠒?huì)有優(yōu)勢(shì),所以我就用了普通的for循環(huán)解決了這個(gè)問(wèn)題革屠。

image

換了一種遍歷方法后凿试,這個(gè)問(wèn)題就解決了,在這里簡(jiǎn)單的做了一些開(kāi)發(fā)時(shí)遇到的坑做了一些總結(jié)似芝,有不同看法的各路大神红省,跪求分享!9酢吧恃!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市麻诀,隨后出現(xiàn)的幾起案子痕寓,更是在濱河造成了極大的恐慌,老刑警劉巖蝇闭,帶你破解...
    沈念sama閱讀 212,383評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呻率,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡呻引,警方通過(guò)查閱死者的電腦和手機(jī)礼仗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)逻悠,“玉大人元践,你說(shuō)我怎么就攤上這事⊥耍” “怎么了单旁?”我有些...
    開(kāi)封第一講書人閱讀 157,852評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)饥伊。 經(jīng)常有香客問(wèn)我象浑,道長(zhǎng)蔫饰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,621評(píng)論 1 284
  • 正文 為了忘掉前任愉豺,我火速辦了婚禮篓吁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蚪拦。我一直安慰自己杖剪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,741評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布外盯。 她就那樣靜靜地躺著,像睡著了一般翼雀。 火紅的嫁衣襯著肌膚如雪饱苟。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 49,929評(píng)論 1 290
  • 那天狼渊,我揣著相機(jī)與錄音箱熬,去河邊找鬼。 笑死狈邑,一個(gè)胖子當(dāng)著我的面吹牛城须,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播米苹,決...
    沈念sama閱讀 39,076評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼糕伐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蘸嘶?” 一聲冷哼從身側(cè)響起良瞧,我...
    開(kāi)封第一講書人閱讀 37,803評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎训唱,沒(méi)想到半個(gè)月后褥蚯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡况增,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,582評(píng)論 2 327
  • 正文 我和宋清朗相戀三年赞庶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澳骤。...
    茶點(diǎn)故事閱讀 38,716評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡歧强,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出为肮,到底是詐尸還是另有隱情誊锭,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評(píng)論 4 333
  • 正文 年R本政府宣布弥锄,位于F島的核電站丧靡,受9級(jí)特大地震影響蟆沫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜温治,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,039評(píng)論 3 316
  • 文/蒙蒙 一饭庞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧熬荆,春花似錦舟山、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,798評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至突琳,卻和暖如春若债,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拆融。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,027評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工蠢琳, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人镜豹。 一個(gè)月前我還...
    沈念sama閱讀 46,488評(píng)論 2 361
  • 正文 我出身青樓傲须,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親趟脂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子泰讽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,612評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容