What you'll be able to do
By the end of this page you should be able to stop a loop as soon as you found what you need (break), skip one item without leaving the whole loop (continue), and decide when those keywords make a search or a filter clearer — and when they just make the path harder to follow.
Previous post: loops — for, while, for…of, for…in.
Who this is for
- People who keep looping after they already found the match
- Beginners who want to “skip empty names” without a nested mess
- Anyone who pasted
breakandcontinueeverywhere and lost the story of the loop
You can skip this if you already use break for “found it, stop,” continue for “skip this item,” and you prefer early if + return inside a function when the whole function should exit. Come back when a loop does extra useless work, or when control jumps feel confusing.
break: leave the loop now
break ends the nearest loop immediately. Code after the loop still runs.
const names = ["Asha", "Ravi", "Mia"];
let found = null;
for (const name of names) {
if (name === "Ravi") {
found = name;
break;
}
}
console.log(found);
That logs Ravi. After break, the loop does not look at "Mia".
Scenario A — search. You are looking for one user id in a list. Once you have it, more iterations waste time. break is the honest stop.
Scenario B — while with an escape hatch. You poll until ready or until a cancel flag is set:
let tries = 0;
let ready = false;
while (tries < 10) {
tries += 1;
// pretend we checked something
if (tries === 3) {
ready = true;
break;
}
}
console.log(ready, tries);
Without break, you might keep spinning even after success. With break, you leave as soon as ready is true.
break does not exit a function by itself — only the loop. To leave a whole function, use return (next phase covers functions deeply).
continue: skip this pass, keep looping
continue jumps to the next iteration of the nearest loop. The rest of the body for this item is skipped.
const raw = ["Asha", "", " ", "Mia"];
for (const name of raw) {
const cleaned = name.trim();
if (cleaned.length === 0) {
continue;
}
console.log("keep", cleaned);
}
That logs keep Asha and keep Mia. Empty and space-only strings are skipped.
Scenario A — dirty list from a form. Some rows are blank. You still want to process the good ones. continue keeps the happy path near the top of the loop body.
Scenario B — same idea with if wrapping. You could write if (cleaned.length > 0) { console.log(...) } instead. That is often clearer for one short action. Prefer continue when the “skip” check is at the top and the rest of the body is long — so you do not nest the whole body in a big if.
break vs continue in one picture
| Keyword | Effect | Typical job |
|---|---|---|
break | Exit the loop entirely | “Found it” / “error, stop trying” |
continue | Skip to next item | “This row is junk, try the next” |
Scenario A — find first error. Walk messages; on the first "error", break and show that message.
Scenario B — count only valid scores. Walk numbers; if Number.isNaN(n), continue; otherwise add to a total. You still need every valid number, so you do not break early.
When not to reach for them
Control keywords are tools, not decorations.
Scenario A — continue that only wraps one line. If the body is a single console.log, a plain if is easier to read than continue.
Scenario B — break deep inside nested loops. break only exits the inner loop. The outer loop keeps going. Beginners expect “stop everything” and get surprised. For this series, keep loops shallow. If you nest two loops and need to leave both, prefer a flag, a labeled break (advanced — skip for now), or move the inner search into a function that returns.
Scenario C — break instead of fixing the condition. A while (true) { ... if (done) break; } works, but a clear while (!done) often tells the story better. Use while (true) + break when several different exits are clearer than one giant condition — not as a default style.
A tiny practice file
Save as break-continue.html. The script finds the first name that starts with "R" using break, then lists non-empty names using continue.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Break and continue</title>
</head>
<body>
<button id="go">Run</button>
<pre id="out">Result will show here.</pre>
<script>
const goButton = document.getElementById("go");
const out = document.getElementById("out");
goButton.addEventListener("click", function () {
const names = ["Asha", "", "Ravi", "Mia"];
const lines = [];
let firstR = null;
for (const name of names) {
if (name.trim().length === 0) {
continue;
}
if (name.startsWith("R")) {
firstR = name;
break;
}
}
lines.push("First R* name: " + firstR);
lines.push("Non-empty names:");
for (const name of names) {
if (name.trim().length === 0) {
continue;
}
lines.push("- " + name);
}
out.textContent = lines.join("\n");
});
</script>
</body>
</html>
Notice the first loop uses both: empty strings are skipped with continue, and the search stops with break once "Ravi" is found — "Mia" is never checked in that loop.
Mistakes I see a lot
1. Expecting break to exit a function. It only exits the loop. Use return for the function.
2. break in the outer loop when you meant the inner one — or the reverse. Know which loop is nearest.
3. continue after you already mutated shared state for this item. Easy to leave half-updated data. Do skips before side effects.
4. Infinite while (true) with a break you never reach. Same freeze as a bad while condition.
5. Using break/continue in forEach. Array forEach does not treat break/continue like a for loop. Stick to for / for...of when you need those keywords (array methods come later in the series).
What to try before the next post
- Search an array for one value and
breakwhen found; log how many steps ran. - Skip falsy or empty strings with
continuein afor...of. - Rewrite one
continueexample as a plainifand compare readability. - Build the tiny HTML file and click once.
This closes Phase 3 of the series (control flow). Next we begin functions: functions from zero — parameters, return values, and the “forgot to return” bug that silently gives undefined.
Try this next outside the series
Control flow starts to stick when it decides real UI and request outcomes.
- React forms without pain — watch conditionals and validation branches show up in a familiar app flow
- Diff Checker — compare before-and-after logic when you refactor branches