JS面試題之forEach能否跳出循環(huán)詳解
當(dāng)年懵懂無(wú)知的我被問(wèn)到這個(gè)問(wèn)題時(shí),腦袋一片空白,當(dāng)然也沒(méi)答對(duì),一直以來(lái)我對(duì)forEach都有一種錯(cuò)誤的理解,由于它比原始的for循環(huán)簡(jiǎn)潔許多,導(dǎo)致我一度認(rèn)為那是為了方便書(shū)寫(xiě)所創(chuàng)造出來(lái)的語(yǔ)法糖,在業(yè)務(wù)中也經(jīng)常使用,但從沒(méi)考慮過(guò)這種方式存在的問(wèn)題。
forEach使用說(shuō)明
參考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach?v=example
arr.forEach(function callback(currentValue, index, array) {
//your iterator
}[, thisArg]);
- currentValue --- 當(dāng)前處理的元素
- index --- 當(dāng)前處理元素的索引
- array ---forEach應(yīng)用的數(shù)組
有一段提示寫(xiě)到了在forEach中break和return的用法。原文如下:
There is no way to stop or break a forEach()loop other than by throwing an exception. If you need such behavior, theforEach()method is the wrong tool. Use a plain loop instead. If you are testing the array elements for a predicate and need a Boolean return value, you can useevery() or
some() instead. If available, the new methodsfind() or findIndex() can be used for early termination upon true predicates as well.
意思就是說(shuō)在forEach中使用break和return是錯(cuò)誤的,如果希望使用break或者return請(qǐng)使用every或者some函數(shù)。
那么回到標(biāo)題,首先f(wàn)orEach是不能使用任何手段跳出循環(huán)的,為什么呢?我們知道forEach接收一個(gè)函數(shù),它一般有兩個(gè)參數(shù),第一個(gè)是循環(huán)的當(dāng)前元素,第二個(gè)是該元素對(duì)應(yīng)的下標(biāo),我們手動(dòng)實(shí)現(xiàn)一下:
Array.prototype.myForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
fn(this[i], i, this);
}
}
forEach是不是真的這么實(shí)現(xiàn)我無(wú)從考究,但是以上這個(gè)簡(jiǎn)單的偽代碼確實(shí)滿足forEach的特性,而且也很明顯就是不能跳出循環(huán),因?yàn)槟愀緵](méi)有辦法操作到真正的for循環(huán)體。
后來(lái)經(jīng)過(guò)查閱文檔,發(fā)現(xiàn)官方對(duì)forEach的定義根本不是我認(rèn)為的語(yǔ)法糖,它的標(biāo)準(zhǔn)說(shuō)法是forEach為每個(gè)數(shù)組元素執(zhí)行一次你所提供的函數(shù)。到這里我的思路逐漸明朗,官方文檔也有這么一段話:
除拋出異常之外,沒(méi)有其他方法可以停止或中斷循環(huán)。如果您需要這種行為,則該forEach()方法是錯(cuò)誤的工具。
使用拋出異常來(lái)跳出foreach循環(huán)
let arr = [0, 1, "stop", 3, 4];
try {
arr.forEach(element => {
if (element === "stop") {
throw new Error("forEachBreak");
}
console.log(element); // 輸出 0 1 后面不輸出
});
} catch (e) {
console.log(e.message); // forEachBreak
};
當(dāng)然,使用try-catch包裹時(shí),當(dāng)循環(huán)體過(guò)大性能會(huì)隨之下降,這是無(wú)法避免的,所以拋出異常并不是解決forEach問(wèn)題的銀彈,我們回歸到開(kāi)頭寫(xiě)的那段偽代碼,我們對(duì)它進(jìn)行一些優(yōu)化,在真正的for循環(huán)中加入對(duì)傳入函數(shù)的判斷:
Array.prototype.forEach = function (fn) {
for (let i = 0; i < this.length; i++) {
let ret = fn(this[i], i, this);
if (typeof ret !== "undefined" && (ret == null || ret == false)) break;
}
}
這樣的話自然就能根據(jù)return值來(lái)進(jìn)行循環(huán)跳出啦:
let arr = [0, 1, "stop", 3, 4];
arr.forEach(element => {
if (element === 'stop') return false
console.log(element); // 輸出 0 1 后面不輸出
});
console.log('return即為continue:');
arr.forEach(element => {
if (element === 'stop') return
console.log(element); // 0 1 3 4
});
文檔中還提到forEach需要一個(gè)同步函數(shù),也就是說(shuō)在使用異步函數(shù)或Promise作為回調(diào)時(shí)會(huì)發(fā)生預(yù)期以外的結(jié)果,所以forEach還是需要慎用或者不要使用,當(dāng)然這并不意味著項(xiàng)目開(kāi)發(fā)中要一直用簡(jiǎn)單的for循環(huán)去完成一切事情,我們可以在遍歷數(shù)組時(shí)使用for..of..,在遍歷對(duì)象時(shí)使用for..in..,而官方也在forEach文檔下列舉了其它一些工具函數(shù):
Array.prototype.find() Array.prototype.findIndex() Array.prototype.map() Array.prototype.filter() Array.prototype.every() Array.prototype.some()
根據(jù)不同的業(yè)務(wù)場(chǎng)景,選擇使用對(duì)應(yīng)的工具函數(shù)來(lái)更有效地處理業(yè)務(wù)邏輯,至于forEach,我想就從此相忘于江湖吧。
總結(jié)
到此這篇關(guān)于JS面試題之forEach能否跳出循環(huán)的文章就介紹到這了,更多相關(guān)JS forEach跳出循環(huán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS 在數(shù)組指定位置插入/刪除數(shù)據(jù)的方法
下面小編就為大家?guī)?lái)一篇JS 在數(shù)組指定位置插入/刪除數(shù)據(jù)的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
多種方法實(shí)現(xiàn)JS動(dòng)態(tài)添加事件
JS動(dòng)態(tài)添加事件的方法有很多,我們可以使用setAttribute、attachEvent 和 addEventListener等等,感興趣的朋友可以參考下2013-11-11
javascript生成隨機(jī)大小寫(xiě)字母的方法
這篇文章主要介紹了javascript生成隨機(jī)大小寫(xiě)字母的方法,需要的朋友可以參考下2014-02-02
微信小程序中使用 async/await的方法實(shí)例分析
這篇文章主要介紹了微信小程序中使用 async/await的方法,結(jié)合實(shí)例形式分析了微信小程序中async/await的功能、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2020-05-05
BootstrapValidator超詳細(xì)教程(推薦)
這篇文章主要介紹了BootstrapValidator超詳細(xì)教程(推薦)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12
JavaScript必看的10道面試題總結(jié)(推薦)
JavaScript 已經(jīng)成為全棧開(kāi)發(fā)技能的基石,在全棧開(kāi)發(fā)面試中都會(huì)不可避免地涉及到與 JavaScript 有關(guān)的問(wèn)題。這篇文章主要給大家介紹了關(guān)于JavaScript必看的10道面試題,需要的朋友可以參考下2021-05-05
原生Js頁(yè)面滾動(dòng)延遲加載圖片實(shí)現(xiàn)原理及過(guò)程
頁(yè)面滾動(dòng)加載事件,獲取元素在頁(yè)面里的top值根據(jù)滾動(dòng)條的位置判斷何時(shí)顯示圖片;獲取元素集合 加載過(guò)的圖片從集合里刪除,具體實(shí)現(xiàn)如下,感興趣的朋友各位可以參考下哈2013-06-06

