JavaScript Loops: while, do...while and for Compared
while checks its condition before running the body; do...while runs the body once before its first condition check. A for loop groups initialization, a condition and an update in one place, making it convenient for counters and indexes. This article compares these three basic JavaScript loops.
| Loop | Condition check | Typical use |
|---|---|---|
| while | Before every iteration | Repeat until a completion condition changes |
| do...while | After every iteration | Perform the action at least once |
| for | After initialization, before every iteration | Repeat with a counter or array index |
while: check first, then run
let i = 0;
while (i < 10) {
console.log(i);
i++;
}
The example tests i < 10, runs the body when it is true, increments i, and checks again. It ends when i reaches 10. An increment is not mandatory in every while loop, but something must eventually change the condition: for example, removing items from a queue can also bring a loop to an end.
do...while: run at least once
let i = 0;
do {
console.log(i);
i++;
} while (i < 10);
Because the body runs first, this loop executes once even if its condition is initially false. Include the final while (condition); in the syntax. It suits a flow that performs an action once and then decides whether to repeat it.
for: combine initialization, condition and update
for (let i = 0; i < 10; i++) {
console.log(i);
}
Initialization runs once. The loop then repeats the condition check, body and update in that order. With i < 10, values run from 0 to 9; changing it to i <= 10 adds an eleventh iteration. A variable declared with let in the loop header belongs to that loop scope. MDN’s loops and iteration guide explains other loop forms as well.
Complete example: compare output and initial conditions
Save this as loops.html in UTF-8 and open it in a browser. Each loop collects values with push(), then join() creates the output text. Separate variables prevent the final state of one loop from affecting the next.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Comparing loops</title>
<style>
body { margin: 24px; font: 16px/1.7 sans-serif; }
input, button, select { font: inherit; max-width: 100%; }
label { display: block; margin-top: 12px; }
#output { white-space: pre-wrap; overflow-wrap: anywhere; }
</style>
</head>
<body>
<p>Compare the values from 0 to 9 produced by three loops.</p>
<pre id="output" aria-live="polite"></pre>
<script>
const whileValues = [];
let i = 0;
while (i < 10) {
whileValues.push(i);
i++;
}
const doValues = [];
let j = 0;
do {
doValues.push(j);
j++;
} while (j < 10);
const forValues = [];
for (let k = 0; k < 10; k++) {
forValues.push(k);
}
let before = 0;
while (false) { before++; }
let after = 0;
do { after++; } while (false);
document.getElementById("output").textContent = [
`while: ${whileValues.join(" ")}`,
`do...while: ${doValues.join(" ")}`,
`for: ${forValues.join(" ")}`,
`Initially false: while ${before} times / do...while ${after} times`
].join("\n");
</script>
</body>
</html>
The first three lines all show 0 1 2 3 4 5 6 7 8 9. The final line shows while 0 times / do...while 1 times, demonstrating the difference when the condition is false from the start. View the rendered result and use the browser’s developer console when examining individual iterations.
break and continue have different effects
for (let i = 0; i < 5; i++) {
if (i === 1) continue;
if (i === 4) break;
console.log(i);
}
// Outputs 0, 2, 3 in order
break ends the current loop. continue skips the rest of the current body. In a for loop, continue proceeds to the update expression; in a while loop, it returns to the condition, potentially skipping an increment placed later in the body. Ensure the loop can still make progress on every path.
Avoid infinite loops and boundary errors
- An accidental semicolon after
while (condition)orfor (...)can create an empty loop body. Check the braces and punctuation. - Array indexes normally run from 0 to length - 1. Use
i < array.lengthunless a different boundary is intentional. - A long synchronous loop can delay rendering and interaction. If an infinite loop freezes the tab, close it and correct the condition or update before reopening the example.
- Consider
for...offor array values.for...inenumerates property names and is not an interchangeable replacement.

