你能在 JavaScript 中跳出 "forEach" 循环吗?
这是一个很棒的问题,可以挑战你对 JavaScript 的真正了解程度。
因为我们不是在讨论 for 循环 — 否则这将会非常简单:你只需要使用 break
:
但你不敢在 forEach
中这样做,否则会发生灾难:
那 return
呢?嗯...
你认为这里会发生什么:
return
应该在 5
时轻松结束循环并带我们到外部的 log
,对吧?
错了:
记住:forEach 接受一个回调函数,并为数组中的每个项目调用它。
// 类似这样的:
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
只是结束当前的回调调用和迭代;对停止整个循环完全没有作用。
就像这里;试图从 func1()
结束 func2()
— 显然不会起作用:
5种糟糕的方式来停止 forEach 循环
1. 抛出异常
你可以通过抛出异常来停止任何 forEach 循环:
当然,我们这里只是在开玩笑 — 在真实世界的代码中看到这样的做法会很糟糕。我们只为问题创建异常,而不是为了这样的计划代码。
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);
});
你不仅结束了循环,还结束了整个程序!
你甚至不会看到这里的 console.log()
:
3. Array.some()
这是不好的做法。
它能工作,一些人推荐用它来做这个;但这降低了可读性,因为它显然不是为此而设计的。
这才是它的设计目的:
const hasEven = [1, 2, 3, 4, 5].some(num => num % 2 === 0);
console.log(hasEven); // true
4. 将数组长度设为 0
但这里有一个更大胆的方法:将数组的长度设置为 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);
});
设置数组的长度完全破坏并重置它 — 变成空数组:
5. 使用 Array.splice()
当你使用 Array.splice()
来停止 forEach 循环时,事情变得更奇怪,在中途删除切割元素!
3种很好的方式来停止循环
1. 你真的需要打破循环吗?
与其使用上面那些可怕的方法来停止 forEach
循环...
为什么不重构你的代码使你根本不需要打破循环?
所以,与其这样:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
nums.forEach((num) => {
if (num === 5) { // ❌ 在数字 5 时退出循环
throw new Error('just to stop a loop?');
}
console.log(num);
});
} catch (e) {
console.log('finally stopped!');
}
我们可以简单地这样做:
2. 使用 for...of
但如果你真的想提前跳出循环,那么使用 for..of
循环会好得多:
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. 使用传统的 for
或者使用传统的 for
循环,以获得更精细的控制:
for (let i = 1; i <= 9; i++) {
console.log(i);
if (i === 5) break;
}
最后的思考
所以有一些方法可以从 forEach 循环"跳出",但它们相当混乱和疯狂。
相反,试着重构代码以避免一开始就需要跳出。或者切换到 for
和 for..of
以获得更清晰、可读的方法。
首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。