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