◆

JavaScript continue 关键字用法详解

2023-02-02 01:370

continue 用来跳过循环中的某一轮,而不是结束整个循环。它最典型的用途是过滤:遍历一批数据时,遇到不符合条件的直接跳过,让后面的处理逻辑不用再套一层 if。用好它能明显减少嵌套层数,代码会平铺得多。

关键要分清它和 break 的区别:break 是「不干了」,continue 是「这条不算,下一条」。下面看语法细节、在不同循环里的执行时机差异,以及一个不注意就会写出死循环的坑。

作用

continue 声明终止当前循环或标记循环的当前迭代中的语句执行,并在下一次迭代时继续执行循环。

与 break 语句的区别在于, continue 并不会终止循环的迭代

语法

continue [label];

label 可选,指定要继续哪一层被标记的循环。不带标签时 continue 只作用于最内层的循环。和 break 一样,它必须写在循环里,放在循环外面(包括 switch 里但不在循环内)是语法错误。

示例

let n = 0;

while (n < 5) {
  n++;
  if (n === 3) {
    continue;
  }
  console.log(n);
}
// 1,2,4,5

输出里只缺了 3,4 和 5 照样打印出来了,这就是「不终止迭代」的意思。如果把 continue 换成 break,输出会变成 1,2——循环直接结束。

while 里的死循环陷阱

上面这段代码能正常结束,是因为 n++ 写在 continue 之前。一旦把推进计数器的语句放到 continue 后面,n 等于 3 那轮就会跳过 n++,n 永远停在 3,条件永远成立,页面直接卡死:

let n = 0;

while (n < 5) {
  if (n === 3) {
    continue; // n 不再增加,死循环
  }
  console.log(n);
  n++;
}

for 不会有这个问题,因为它的迭代表达式在循环体之后由语句本身执行,continue 只跳过循环体,i++ 照样会跑:

for (let i = 0; i < 5; i++) {
  if (i === 3) continue; // i++ 仍然执行,不会死循环
  console.log(i);
}
// 0,1,2,4

所以在 while 里用 continue 时,先确认条件变量在 continue 之前已经推进过了。

用它减少嵌套

continue 的实际价值主要在这里。带着多个前置校验遍历数据时,用 if 层层包起来会越写越深,用 continue 提前跳过就平了:

// 嵌套写法
for (const user of users) {
  if (user.active) {
    if (user.age >= 18) {
      send(user);
    }
  }
}

// 用 continue 提前跳过,逻辑主线一眼能看到
for (const user of users) {
  if (!user.active) continue;
  if (user.age < 18) continue;
  send(user);
}

这和函数里的卫语句(early return)是同一个思路:先把不处理的情况一条条排除掉,剩下的就是正常流程。

带标签的 continue

嵌套循环里,内层的 continue 只影响内层。想跳到外层的下一轮迭代,就给外层循环加标签:

outer: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (j === 1) {
      continue outer; // 直接进入外层的下一轮,i++
    }
    console.log(i, j);
  }
}
// 输出 0 0 / 1 0 / 2 0

每次 j 等于 1 时就放弃内层剩下的迭代,回到外层执行 i++,所以每个 i 只输出了 j 等于 0 的那一次。注意 continue outer 是继续外层的下一轮,不是结束外层——那是 break outer 的事。

用不了 continue 的地方

forEach、map、filter 这类数组方法的回调是独立的函数体,里面没有循环结构可以作用,写 continue 会直接报语法错误。它们的等价写法是 return:回调 return 就等于结束当前这次调用,效果和 continue 一样。

// users.forEach(u => { if (!u.active) continue; });  // 语法错误

users.forEach(u => {
  if (!u.active) return; // 相当于 continue,跳过这一项
  send(u);
});

不过遇到这种需求,更自然的做法是先 filter 再处理,链式写法比在回调里提前 return 意图更清楚:users.filter(u => u.active).forEach(send)。

💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVEJavaScript continue 关键字用法详解加载中