终止JS forEach循环

152 阅读2分钟

最近在看一些面试题,有一个题非常有意思,如何中断forEach的循环。因为forEach不像for循环这种很直观的遍历,如果在forEach中使用return的话,会直接进入下一次循环,而for循环的话则会跳出循环。因此想要跳出forEach 的循环的话,需要使用别的方法。

想要实现跳出forEach循环的方法,就要先了解forEach这种循环的底层原理。

我们先自己实现一个forEach

//写一个自己实现的forEach,实现打印出arr内的所有元素
const arr = ["a", "b", "c"];

for (let i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}
//a b c

//这里第一个参数是item,第二个是index,第三个参数就是Arr本身,这样就实现了myForEach
//切记这里不能使用箭头函数,箭头函数没有this,这个方法是绑定到原型上的,如果使用监听函数就获取不到this
Array.prototype.myForEach = function(fn){
  for (let i = 0; i < this.length; i++) {
    fn(this[i],i,this)
  }
};

//传入的是一个函数,这里的原数组以this的来传递
arr.myForEach((item) => console.log(item));
//arr.map((item) => console.log(item));

因此从我们写的这个demo中可以看出,如果我们想要直接跳出循环的话,return是行不通的,直接return只会进入下一次循环。因此我们可以使用以下方法

1.抛出异常

 try {
   array.forEach((item) => {
     if () {
       console.log(item) // 输出:0
       throw Error(`out`)
     }
   })
 } catch (err) {}

通过抛出异常的方式即可实现,而且如果你使用forEach的话,MDN文档也只推荐使用该方法跳出,但是如果想要有跳出的效果的话,还是使用for遍历,或者some,for...of

2.改变原数组的长度(不推荐)

可以将原数组的长度设置为0或者直接移除遍历的元素,实现跳出循环

 const array = [ 1 ,2 , 3 ]
 ​
 array.forEach((item, index) => {
   if (item >= 0) {
     array.splice(index + 1, array.length - index)
     //直接移除了arr后面未遍历的数,实现了跳出循环
   }
 })

在调用forEach中是不会改变元素组的

 const array = [1, 2, 3, 4];
 array.forEach((ele) => {
     ele = ele * 3;
 });
 console.log(array); // [ 1, 2, 3, 4 ]

但是如果item是一个引用对象的话,如此操作会改变原来的元素

 const numArr = [3, 4, 5];
 numArr.forEach((ele, index, arr) => {
     if (ele === 3) {
         arr[index] = 9;
     }
 });
 console.log(numArr); // [ 9, 4, 5 ]

由于forEach在执行过程中会保存上下文作用域,因此如果在算法中使用想要提升效率的话,可以优化为for循环