Skip to content
aviral gupta

// B3.4 · ~30 min · Beginner

break and continue

After this lesson you stop a loop at the first match, skip bad entries without stopping, and know where break and continue are allowed.

Lesson 4 of 5 in B3 Control flow and loops

You will be able to

  • Stop a loop at the first match with break, and know that break in a switch leaves only the switch
  • Skip invalid entries with continue, and keep it from skipping the update of a while loop
  • Read a labelled break, and fix the SyntaxErrors of a break or continue in the wrong place
  1. Warm-up · Activity 1 of 7

    Warm-up: which keyword ends a loop at once, so that the program carries on after the loop?

  2. Predict · Activity 2 of 7

    Predict before you read on: what does this print?

    for (let i = 1; i <= 5; i++) {
      if (i === 3) {
        continue;
      }
      console.log(i);
    }
  3. Practice · Activity 3 of 7

    Fill in the keyword so that the program prints the first temperature above 30, which is 31, and stops looking.

    const temps = [12, 18, 31, 25, 33];
    let firstHot;
    for (const t of temps) {
      if (t > 30) {
        firstHot = t;
        ____;
      }
    }
    console.log(firstHot);
    ;
  4. Practice · Activity 4 of 7

    A switch inside a loop. What does this print?

    const commands = ["go", "stop", "go"];
    for (const c of commands) {
      switch (c) {
        case "stop":
          console.log("stopping");
          break;
        default:
          console.log("going");
      }
    }
  5. Practice · Activity 5 of 7

    Each line goes first in the block of for (const n of [1, 2, 3, 4]) { … console.log(n); }. Match it to the numbers the loop prints.

  6. Brain teaser · Activity 6 of 7

    Brain teaser. Do not run this one. What happens?

    let i = 0;
    while (i < 5) {
      if (i === 2) {
        continue;
      }
      console.log(i);
      i++;
    }
  7. Apply · Activity 7 of 7

    Mini-task. Write a step counter log. Put daily step counts in an array, with some bad entries such as "n/a" or -1. Loop over the days with a counting for loop: print Day 2: no data for a bad entry and skip it with continue, print Day 1: 5200 steps for a good one, and stop with break on the first day that reaches a goal of 10000. Last, print Goal reached on day 5 (or Goal not reached).

    Check your work against this list

Build it yourself

Read the worked example, then write the exercises. Your code runs in your browser or on your computer and is never uploaded.

Worked example

Scan a thermometer log

A thermometer logged eight readings, but two are bad: a text "error" and the value -999, which the device writes when it fails. The program skips the bad ones with continue, adds up the good ones, and stops with break at the first reading above 30, the alarm. Run it, then change 31.5 to 29 and predict the output before you run it again.

main.js

// Scan the readings of a thermometer.
const readings = [21.5, 22, "error", 23.5, -999, 24, 31.5, 25];
let total = 0;
let count = 0;
let firstAlarm;

for (const r of readings) {
  if (typeof r !== "number" || r < -50) {
    console.log("skip:", r);
    continue;
  }
  total += r;
  count++;
  if (r > 30) {
    firstAlarm = r;
    break;
  }
}

console.log("used", count, "readings");
console.log("average", (total / count).toFixed(1));
console.log("first alarm:", firstAlarm);

Run it with

node main.js

Output

skip: error
skip: -999
used 5 readings
average 24.5
first alarm: 31.5
  • continue skips the bad readings: they are printed, but never added or counted.
  • break ends the loop at 31.5, so the last reading, 25, is never used.
  • The average is worked out after the loop, from the readings that were used: 122.5 / 5.
  • With no reading above 30, the loop runs to the end and firstAlarm stays undefined.
Change it and run it

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.

Exercises

Exercise 1 of 2

Stop at the first match

The program should report the first price above the budget and stop looking, but it reports the last one and checks every price. Make it print First price above 10: 12 at position 1 and then Checked 2 prices. Keep the counter checked++ as the first line of the loop.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.

Hints
  1. Hint 1

    Run the starter: it reports 25, because every later match overwrites found.

  2. Hint 2

    Once found and position are set, nothing more needs checking. Which keyword ends the loop at once?

  3. Hint 3

    Add break; as the last line inside the if.

Show a solution

One way to solve it. Yours can look different and still pass the checks.

const prices = [4.5, 12, 7.25, 19.99, 3, 25];
const budget = 10;
let found;
let position;
let checked = 0;

for (let i = 0; i < prices.length; i++) {
  checked++;
  if (prices[i] > budget) {
    found = prices[i];
    position = i;
    break;
  }
}

console.log(`First price above ${budget}: ${found} at position ${position}`);
console.log(`Checked ${checked} prices`);
Run it on your computer

Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.js

const prices = [4.5, 12, 7.25, 19.99, 3, 25];
const budget = 10;
let found;
let position;
let checked = 0;

for (let i = 0; i < prices.length; i++) {
  checked++;
  if (prices[i] > budget) {
    found = prices[i];
    position = i;
  }
}

console.log(`First price above ${budget}: ${found} at position ${position}`);
console.log(`Checked ${checked} prices`);

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';

const lines = async () => (await runMain()).trimEnd().split('\n');

test('reports the first price above the budget', async () => {
  const got = await lines();
  assert.equal(got[0], 'First price above 10: 12 at position 1', `the first line is ${JSON.stringify(got[0])}, expected "First price above 10: 12 at position 1"`);
});

test('stops looking after the match', async () => {
  const got = await lines();
  assert.equal(got[1], 'Checked 2 prices', `the second line is ${JSON.stringify(got[1])}, expected "Checked 2 prices"`);
});

test('prints exactly two lines', async () => {
  const got = await lines();
  assert.equal(got.length, 2, `the program printed ${got.length} line(s), expected 2`);
});

package.json

{
  "type": "module"
}

package.json tells Node.js that the .js files are modules; keep it in the folder.

Run the program:

node main.js

Run the checks (needs learnrun.js in the same folder):

node --test
Download learnrun.js

Exercise 2 of 2

Skip the bad entries

An order form sent these quantities, and some are not usable. Skip every entry that is not a number or is not above 0: print Skipped: two (with the entry) and go on with the next one using continue. Add up the others and count them, and print Total: 12 from 3 entries at the end.

Tab indents and Shift+Tab outdents. To leave the editor with the keyboard, press Esc, then Tab.

The first run downloads the JavaScript runner (up to 0.1 MB) and keeps it cached. Your code runs in your browser’s own engine and stays on your device.

Hints
  1. Hint 1

    Run the starter: "two" turns the total into text, and 0 and -1 are counted too.

  2. Hint 2

    A bad entry is one where typeof q !== "number" || q <= 0. Test that first in the loop.

  3. Hint 3

    Inside that if, print the line, then write continue; so that the adding below is skipped for this entry.

Show a solution

One way to solve it. Yours can look different and still pass the checks.

const quantities = [3, "two", 0, 5, -1, 4];
let total = 0;
let used = 0;

for (const q of quantities) {
  if (typeof q !== "number" || q <= 0) {
    console.log(`Skipped: ${q}`);
    continue;
  }
  total += q;
  used++;
}

console.log(`Total: ${total} from ${used} entries`);
Run it on your computer

Install ECMAScript 2026 or newer. Save these files in one folder, open a terminal in that folder, and run the commands below.

main.js

const quantities = [3, "two", 0, 5, -1, 4];
let total = 0;
let used = 0;

for (const q of quantities) {
  // Skip anything that is not a number above 0.
  total += q;
  used++;
}

console.log(`Total: ${total} from ${used} entries`);

main.test.js

import {test} from 'node:test';
import assert from 'node:assert/strict';
import {runMain} from './learnrun.js';

const lines = async () => (await runMain()).trimEnd().split('\n');

test('reports each bad entry', async () => {
  const got = await lines();
  assert.deepEqual(got.slice(0, 3), ['Skipped: two', 'Skipped: 0', 'Skipped: -1'], `the first three lines are ${JSON.stringify(got.slice(0, 3))}`);
});

test('adds up only the good entries', async () => {
  const got = await lines();
  assert.equal(got[got.length - 1], 'Total: 12 from 3 entries', `the last line is ${JSON.stringify(got[got.length - 1])}, expected "Total: 12 from 3 entries"`);
});

test('prints exactly four lines', async () => {
  const got = await lines();
  assert.equal(got.length, 4, `the program printed ${got.length} line(s), expected 4`);
});

package.json

{
  "type": "module"
}

package.json tells Node.js that the .js files are modules; keep it in the folder.

Run the program:

node main.js

Run the checks (needs learnrun.js in the same folder):

node --test
Download learnrun.js

Common mistakes

break to leave an if

const score = 120;
if (score > 100) {
  console.log("too high");
  break;
}
console.log("score", score);

What Node.js prints

SyntaxError: Illegal break statement

Why, and the fix

break ends a loop or a switch, and an if is neither. Outside a loop or switch the file cannot be read, so not even the first line runs. To leave an if early, put the rest of the work in an else, or turn the test round: if (score <= 100) { … }.

continue in a switch that is not in a loop

const day = "sun";
switch (day) {
  case "sun":
    console.log("closed");
    continue;
  default:
    console.log("open");
}

What Node.js prints

SyntaxError: Illegal continue statement: no surrounding iteration statement

Why, and the fix

continue means "go on with the next pass of the loop", and here there is no loop around the switch, only the switch. A case ends with break, not continue. Inside a loop, continue in a case is allowed and goes on with the loop’s next pass.

A misspelled label

outer: for (const row of [1, 2]) {
  for (const col of [1, 2]) {
    if (row === col) {
      break outr;
    }
    console.log(row, col);
  }
}

What Node.js prints

SyntaxError: Undefined label 'outr'

Why, and the fix

A label works only if break or continue names it exactly and stands inside the statement it labels. outr is not outer, so JavaScript finds no such label around the break, and the whole file cannot be read. Write break outer;, or use a plain break if leaving the inner loop is enough.

JavaScript in the browser: your browser’s own engine, in a sandboxed worker. Syntax errors are located with acorn 8.18.0, MIT. Licence and source

Exit ticket

5 questions, no hints. Score 80% or more to complete the lesson.

Finish every activity above to unlock the exit ticket.

Report a problem

Spotted something wrong or unclear? Say what, and it will be checked and fixed.

#

At least 20 characters.

Only if you want a reply.

Key ideas

break: stop as soon as you have it

break ends the loop it stands in, at once, and the program carries on with the first statement after that loop. That is how you stop at the first match: for (const p of prices) { if (p > budget) { found = p; break; } }. Without the break, the loop keeps going, a later match overwrites found, and you get the last match instead of the first, after more work. break works the same in for, while and for...of. Inside a switch, break leaves only the switch: in a switch inside a loop, the loop goes on with its next pass.

continue: skip this pass, keep going

continue ends only the current pass and goes on with the next one. It suits skipping bad entries: put the test first, if (typeof score !== "number") { continue; }, and the rest of the block handles good values only. Where it jumps depends on the loop: in for...of, to the next value; in a for loop, to the update, so i++ still runs; in a while loop, straight back to the condition. So if a while loop changes its counter at the end of the block, a continue above that line skips it, the condition never changes, and the loop never ends. Change the counter first, or use a for loop.

Where they are allowed, and labels

break and continue belong inside a loop, and break also inside a switch. Anywhere else the file cannot be read, so nothing runs. A break at the top level, for example to leave an if, gives SyntaxError: Illegal break statement; use else instead. A continue outside a loop gives SyntaxError: Illegal continue statement: no surrounding iteration statement. A label names a statement: outer: for (…) { for (…) { break outer; } } ends both loops at once, and continue outer; goes on with the outer loop’s next pass. Labels are rare, and a misspelled one is a SyntaxError too: Undefined label.

Sources

Last reviewed October 3, 2026