你實(shí)際上可以用這五種方式打破 JavaScript 中的 forEach 循環(huán)
這是一個(gè)很棒的問(wèn)題,可以挑戰(zhàn)你對(duì) JavaScript 的真正了解程度。
因?yàn)槲覀儾皇窃谟懻?nbsp;for 循環(huán) — 否則這將會(huì)非常簡(jiǎn)單:你只需要使用 break:
圖片
但你不敢在 forEach 中這樣做,否則會(huì)發(fā)生災(zāi)難:
圖片
那 return 呢?嗯...
你認(rèn)為這里會(huì)發(fā)生什么:
圖片
return 應(yīng)該在 5 時(shí)輕松結(jié)束循環(huán)并帶我們到外部的 log,對(duì)吧?
錯(cuò)了:
圖片
記?。篺orEach 接受一個(gè)回調(diào)函數(shù),并為數(shù)組中的每個(gè)項(xiàng)目調(diào)用它。
// 類(lèi)似這樣的:
Array.prototype.forEach = function (callback, thisCtx) {
const length = this.length;
let i = 0;
while (i < length) {
// ?? callback 僅運(yùn)行一次
callback.call(thisCtx, this[i], i, this);
i++;
}
};
所以 return 只是結(jié)束當(dāng)前的回調(diào)調(diào)用和迭代;對(duì)停止整個(gè)循環(huán)完全沒(méi)有作用。
就像這里;試圖從 func1() 結(jié)束 func2() — 顯然不會(huì)起作用:
圖片
5種糟糕的方式來(lái)停止 forEach 循環(huán)
1. 拋出異常
你可以通過(guò)拋出異常來(lái)停止任何 forEach 循環(huán):
圖片
當(dāng)然,我們這里只是在開(kāi)玩笑 — 在真實(shí)世界的代碼中看到這樣的做法會(huì)很糟糕。我們只為問(wèn)題創(chuàng)建異常,而不是為了這樣的計(jì)劃代碼。
2. process.exit()
這個(gè)方法更極端:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
nums.forEach((num) => {
if (num === 5) {
process.exit(0);
}
console.log(num);
});
你不僅結(jié)束了循環(huán),還結(jié)束了整個(gè)程序!
你甚至不會(huì)看到這里的 console.log():
圖片
3. Array.some()
這是不好的做法。
圖片
它能工作,一些人推薦用它來(lái)做這個(gè);但這降低了可讀性,因?yàn)樗@然不是為此而設(shè)計(jì)的。
這才是它的設(shè)計(jì)目的:
const hasEven = [1, 2, 3, 4, 5].some(num => num % 2 === 0);
console.log(hasEven); // true
4. 將數(shù)組長(zhǎng)度設(shè)為 0
但這里有一個(gè)更大膽的方法:將數(shù)組的長(zhǎng)度設(shè)置為 0!
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
nums.forEach((num) => {
if (num === 5) {
process.exit(0);
}
console.log(num);
});
設(shè)置數(shù)組的長(zhǎng)度完全破壞并重置它 — 變成空數(shù)組:
圖片
5. 使用 Array.splice()
當(dāng)你使用 Array.splice() 來(lái)停止 forEach 循環(huán)時(shí),事情變得更奇怪,在中途刪除切割元素!
圖片
3種很好的方式來(lái)停止循環(huán)
1. 你真的需要打破循環(huán)嗎?
與其使用上面那些可怕的方法來(lái)停止 forEach 循環(huán)...
為什么不重構(gòu)你的代碼使你根本不需要打破循環(huán)?
所以,與其這樣:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
nums.forEach((num) => {
if (num === 5) { // ? 在數(shù)字 5 時(shí)退出循環(huán)
throw new Error('just to stop a loop?');
}
console.log(num);
});
} catch (e) {
console.log('finally stopped!');
}
我們可以簡(jiǎn)單地這樣做:
圖片
2. 使用 for...of
但如果你真的想提前跳出循環(huán),那么使用 for..of 循環(huán)會(huì)好得多:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
for (const num of nums) {
if (num === 5) {
break; // ?? break works
}
console.log(num);
}
} catch {
console.log('finally stopped!');
}
3. 使用傳統(tǒng)的 for
或者使用傳統(tǒng)的 for 循環(huán),以獲得更精細(xì)的控制:
for (let i = 1; i <= 9; i++) {
console.log(i);
if (i === 5) break;
}
最后的思考
所以有一些方法可以從 forEach 循環(huán)"跳出",但它們相當(dāng)混亂和瘋狂。
相反,試著重構(gòu)代碼以避免一開(kāi)始就需要跳出。或者切換到 for 和 for..of 以獲得更清晰、可讀的方法。