JavaScriptBreak & Continue

break and continue

break and continue are the two ways to short-circuit a loop. break ends the loop entirely; continue skips to the next iteration. They are simple, well-known, and slightly more nuanced than they look — especially around nested loops, switch blocks, and the loops that can't be broken out of.

break: stop the loop

JS
function firstEven(numbers) {
  for (const n of numbers) {
    if (n % 2 === 0) {
      return n;
    }
  }
  return undefined;
}

// or without return:
function indexOfFirstEven(numbers) {
  let found = -1;
  for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
      found = i;
      break;
    }
  }
  return found;
}

Once break runs, control jumps to the statement after the loop. Anything queued up below in the loop body is skipped.

continue: skip this iteration

continue jumps straight to the next iteration. In a for loop, the update step still runs. In a while, the condition is checked next.

JS
for (let i = 0; i < 10; i++) {
  if (i % 2 === 0) continue;   // skip evens
  console.log(i);
}
1
3
5
7
9
continue is often a filter in disguise
A loop that starts with `if (...) continue;` is doing the same job as `array.filter(...).forEach(...)`. When you only filter, prefer the array method. When you also want to break or use the index, keep the loop.
Both inside one loop

JS
for (const line of lines) {
  if (line.startsWith("#")) continue;   // skip comments
  if (line === "END") break;            // stop at sentinel
  process(line);
}

The pattern reads almost as English: "for each line, skip comments, stop at the sentinel, otherwise process". This is the kind of place loops still beat array methods on clarity.

Inside nested loops

A plain break only exits the innermost enclosing loop. The outer loop continues.

JS
for (let r = 0; r < grid.length; r++) {
  for (let c = 0; c < grid[r].length; c++) {
    if (grid[r][c] === target) {
      console.log("found at", r, c);
      break;       // exits the inner loop only
    }
  }
}

Three idiomatic ways to escape the outer loop too:

  • Pull the inner loop into a function and return — cleanest in most cases.

  • Set a flag and check it at the top of the outer loop.

  • Use a labelled break — see the Labels page.

The function-and-return version

JS
function find(grid, target) {
  for (let r = 0; r < grid.length; r++) {
    for (let c = 0; c < grid[r].length; c++) {
      if (grid[r][c] === target) return [r, c];
    }
  }
  return null;
}
Inside switch — break vs return

break inside a switch exits the switch, not any surrounding loop. That makes it noisy when a switch is nested in a loop: a "loop break" looks identical to a "switch break".

JS
for (const event of events) {
  switch (event.type) {
    case "STOP":
      // break here only exits the switch — the loop keeps going.
      // To exit the loop you need a labelled break or a flag.
      break;
    default:
      handle(event);
  }
}
Prefer return when you can
In any function, `return` exits cleanly through every nesting level without ambiguity. If your loop lives inside a function, return is usually clearer than break + flags.
Where they don't work: forEach

Array.prototype.forEach, map, filter, reduce etc. accept a callback — and you cannot break out of a callback. continue and break would throw "Illegal break/continue statement".

This does NOT work

JS
[1, 2, 3, 4].forEach(n => {
  if (n === 3) break;          // SyntaxError
  console.log(n);
});

The alternatives:

  • some() — returns true and stops the moment the callback returns truthy. Use when you want "stop as soon as I find one".

  • every() — stops on the first falsy callback. Use for "are they all valid?".

  • for...of — supports break and continue natively. Use when you want imperative control.

  • return in forEach's callback acts like continue, not break. The loop still runs to the end.

some() = forEach with early exit

JS
const hasNegative = numbers.some(n => n < 0);    // stops at first negative
continue and the update step

Subtle but important: in a classic for (init; cond; update) loop, continue runs the update before re-checking the condition. In a while, it goes straight back to the condition. Forgetting that is how continue produces an accidental infinite loop:

Infinite loop trap

JS
let i = 0;
while (i < 10) {
  if (i === 5) continue;       // never increments i past 5
  console.log(i);
  i++;
}

The fix is to increment before the continue, or to switch to a for loop where the update is in the header.

One sentence to remember
`break` exits the nearest loop or switch, `continue` skips to the next iteration — and neither works inside `forEach`, where `some`/`every` or `for...of` are your tools.