使用抛出异常来跳出foreach循环
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
};
那么可不可以认为,forEach可以跳出循环,使用抛出异常就可以了?这点我认为仁者见仁智者见智吧,在forEach的设计中并没有中断循环的设计,而使用try-catch包裹时,当循环体过大性能会随之下降,这是无法避免的,所以抛出异常可以作为一种中断forEach的手段,但并不是为解决forEach问题而存在的银弹。
再次回归到开头写的那段伪代码,对它进行一些优化,在真正的for循环中加入对传入函数的判断:
// 为避免争议此处不再覆写原有forEach函数
Array.prototype.myForEach = 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;
}
}
这样的话就能根据return值来进行循环跳出啦:
let arr = [0, 1, "stop", 3, 4];
arr.myForEach(x => {
if (x === 'stop') return false
console.log(x); // 输出 0 1 后面不输出
});
// return即为continue:
arr.myForEach(x => {
if (x === 'stop') return
console.log(x); // 0 1 3 4
});
文档中还提到forEach需要一个同步函数,也就是说在使用异步函数或Promise作为回调时会发生预期以外的结果,所以forEach还是需要慎用。
当然,用简单的for循环去完成一切事情也不失为一种办法,代码首先是写给人看的,附带能在机器上运行的作用,forEach在很多时候用起来更加顺手,但也务必在理解JS如何设计这些工具函数的前提下来编写我们的业务代码。