JavaScript: Continue vs Break vs Return

387 阅读5分钟

continue: 只是停止了当前循环,继续执行后面的循环,当循环执行完继续执行fn函数里之后的语句

break: 结束整个循环体,跳出循环来继续执行fn函数里之后的语句

return: 停止这个循环,跳出循环并且停止执行fn函数里后边的语句

我们将用基本循环来说明,每个迭代打印i的值:

for (let i = 1; i <= 10; i++){
  console.log(i);
}
//运行结果:
1
2
3
4
5
6
7
8
9
10

Continue

如果我们只想打印偶数怎么办? 在每次迭代中,我们可以检查i是否为奇数。 如果是这样,我们将使用continue语句停止执行当前迭代。如果i是偶数,我们可以继续操作,并console.log记录i的值。该代码如下所示:

for (let i = 1; i <= 10; i++){
  if (i % 2 == 1) continue;
  console.log(i);
}
//运行结果:
2
4
6
8
10

记住,当我们使用continue语句时,循环迭代立即停止执行。 因此,console.log代码永远不会对奇数执行。

Break

由于某些原因,这次我们希望在i为6时完全停止执行循环。为此,我们将插入另一个条件测试i,如果测试通过,我们将中断循环执行:

for (let i = 1; i <= 10; i++){
  if (i == 6) break;
  console.log(i);
}
//运行结果:
1
2
3
4
5
//说明:如果运行此代码,则循环会在测试i == 6之后立即停止执行。这意味着6将不会登录到控制台

嵌套循环

for (let i = 0; i < 5; i++) {
   if (i % 2 == 0) continue;
   for (let j = 0; j < 5; j++) {
      if (j == 2) break;
      console.log(`i = ${i}, j = ${j}`);
   }
}
//运行结果:
i = 1,j = 0
i = 1,j = 1
i = 3,j = 0
i = 3,j = 1

Return

return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。不再执行下面的代码(结束当前的方法 直接返回)

(function () {
    for (let i = 0; i <= 10; i++) {
        if(i === 3){
            return;
        }
        console.log(i);
    }
    console.log("如果i等于3,不会运行到这里");
})();
//运行结果:
0
1
2

forEach如何跳出循环?

forEach() 的定义:对数组的每个元素执行一次提供的函数。

forEach中return/return false/return true 只用于跳过本次循环,而不是整个循环,所以使用return没有效果。

使用break语句会报错。

[0,1,2,3,4,5].forEach((item)=>{
	if(item == 2) return;
	console.log(item);
})
//运行结果:
0
1
3
4
5

MDN文档上明确说明forEach循环是不可以退出的。

引自MDN There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.

注意: 没有办法中止或者跳出 forEach() 循环,除了抛出一个异常。如果你需要这样,使用 forEach() 方法是错误的。

若你需要提前终止循环,你可以使用:

简单循环

for...of 循环

Array.prototype.every()

Array.prototype.some()

Array.prototype.find()

Array.prototype.findIndex()

探究为什么break和return不行

const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
  const rs = (function(item) {
    console.log(item);
    if (item > 2) return false;
  })(arr[i])
}

使用return语句相当于在每个自执行函数中将返回值复制给rs,但是实际对整个函数并没有影响。而使用break语句报错是因为再JS的解释器中break语句是不可以出现在函数体内的。

如何变通跳出forEach循环

MDN官方推荐的方法

every在碰到return false的时候,中止循环。some在碰到return ture的时候,中止循环。

var a = [1, 2, 3, 4, 5]
a.every(item=>{
    console.log(item); //输出:1,2
    if (item === 2) {
        return false
    } else {
        return true
    }
})
var a = [1, 2, 3, 4, 5]
a.some(item=> {
    console.log(item); //输出:1,2
    if (item === 2) {
        return true
    } else {
        return false
    }
})

其他方法

  • 1 使用for循环或者for in 循环代替
  • 2 使用throw抛出异常
try {
  [1, 2, 3, 4, 5].forEach(function(item) {
    if (item=== 2) throw item;
    console.log(item);
  });
} catch (e) {}

  • 3 使用判断跑空循环
[1, 2, 3, 4, 5].forEach(function(item){
    if(!this.tag){
        console.log(item);
        if(item===2){
            this.tag=true;
        }
    }
},{})

- 4 修改索引
var array=[1, 2, 3, 4, 5]
array.forEach(item=>{
  if (item == 2) {
    array = array.splice(0);
  }
  console.log(item);
})

forEach的执行细节讲解:

  • 1 遍历的范围在第一次执行callback的时候就已经确定,所以在执行过程中去push内容,并不会影响遍历的次数,这和for循环有很大区别,下面的两个案例一个会造成死循环一个不会。
var arr=[1,2,3,4,5]
//会造成死循环的代码
for(var i=0;i<arr.length;i++){
    arr.push('a')
}
//不会造成死循环
arr.forEach(item=>arr.push('a'))

  • 2 如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。
var arr=[1,2,3,4,5];
arr.forEach((item,index)=>{
    console.log(`time ${index}`)
    arr[index+1]=`${index}a`;
    console.log(item)
})

- 3 已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()),之后的元素将被跳过。
var array=[1, 2, 3, 4, 5]
array.forEach(item=>{
  if (item == 2) {
    array = array.splice(0);
  }
  console.log(item);
})
// 如果数组在迭代时被修改了,则其他元素会被跳过
var words = ['one', 'two', 'three', 'four'];
words.forEach(function(word) {
  console.log(word);
  if (word === 'two') {
    words.shift();
  }
});
//运行结果:
one
two
four