JavaScript While Loop
A while loop repeats a block of code for as long as a given condition stays true. It’s the most fundamental looping construct in JavaScript: simpler than a for loop because it has no built-in initializer or update step, which makes it perfect for situations where you don’t know in advance exactly how many times you’ll need to repeat something — for example, reading from a queue until it’s empty, or retrying an operation until it succeeds.
Overview / How It Works
A while loop consists of a condition and a body. Before every single iteration — including the very first one — the JavaScript engine evaluates the condition. If the condition is truthy, the body runs once, and then the engine jumps back and re-checks the condition. This repeats until the condition evaluates to something falsy (false, 0, "", null, undefined, or NaN), at which point the loop ends and execution continues with the statement after the loop.
Because the check happens before the body runs, a while loop’s body might execute zero times if the condition is already false on the first check. JavaScript also provides a variant, do...while, that checks the condition after the body runs, guaranteeing the body executes at least once. Both loops create their own lexical scope for any let or const variables declared inside them, but variables declared with let/const outside the loop persist across iterations, which is exactly what lets a loop variable accumulate changes over time.
Unlike a for loop, a while loop doesn’t force you to write an initializer or an increment/decrement expression as part of its syntax. That flexibility is powerful, but it also means you are responsible for making sure the condition eventually becomes false — otherwise the loop runs forever and freezes your program (an infinite loop).
Syntax
The general form of a while loop is:
while (condition) {
// code to execute while condition is true
}
The general form of a do...while loop is:
do {
// code to execute at least once
} while (condition);
| Part | Description |
|---|---|
condition |
Any expression that is coerced to a boolean before each check. The loop continues while it is truthy. |
| Loop body | The block of statements between { and } that runs on each iteration. |
break |
Immediately exits the loop, skipping any remaining iterations. |
continue |
Skips the rest of the current iteration’s body and jumps straight to the next condition check. |
Trailing ; |
Required after the while (condition) in a do...while loop, but not after a plain while loop’s closing brace. |
Examples
Example 1: Basic counting
let count = 1;
while (count <= 5) {
console.log(`Count is ${count}`);
count++;
}
console.log('Done counting!');
Output:
Count is 1
Count is 2
Count is 3
Count is 4
Count is 5
Done counting!
Here count starts at 1. Before each iteration, JavaScript checks whether count <= 5. As long as that’s true, it logs the current value and then increments count. Once count becomes 6, the condition is false, the loop exits, and the final line runs.
Example 2: Processing a task queue
const tasks = ['email', 'backup', 'report', 'cleanup'];
while (tasks.length > 0) {
const task = tasks.shift();
console.log(`Processing task: ${task}`);
}
console.log('All tasks complete.');
Output:
Processing task: email
Processing task: backup
Processing task: report
Processing task: cleanup
All tasks complete.
This is a very common real-world pattern: the loop condition isn’t a counter at all, it’s tasks.length > 0. Each iteration removes one item from the front of the array with shift(), which shrinks tasks.length by one. The loop naturally ends once the array is empty — you never had to know in advance how many tasks there were.
Example 3: do…while for guaranteed first execution
const inputs = ['5', '3', 'quit'];
let index = 0;
let total = 0;
let input;
do {
input = inputs[index];
index++;
if (input !== 'quit') {
const num = Number(input);
total += num;
console.log(`Added ${num}. Running total: ${total}`);
}
} while (input !== 'quit');
console.log(`Final total: ${total}`);
Output:
Added 5. Running total: 5
Added 3. Running total: 8
Final total: 8
This simulates reading a stream of input values (like a form or a CLI prompt) until a 'quit' sentinel appears. A do...while is a natural fit here because you always want to read at least one value before deciding whether to stop — you can’t check the condition on input until you’ve actually read something into it.
Under the Hood
When the engine encounters a while statement, it performs roughly these steps on repeat:
- Evaluate the condition expression and coerce the result to a boolean using the same rules as
Boolean(value)(this is called ToBoolean internally). - If the result is
false, control jumps to the statement immediately after the loop — the body never runs (or stops running). - If the result is
true, the engine executes every statement inside the loop’s block, creating a fresh block scope for anylet/constdeclared directly inside the body on that pass. - After the body finishes (or a
continueis hit), control jumps back to step 1 and re-evaluates the condition. - A
breakstatement anywhere in the body immediately abandons the loop, jumping to the code after it — the condition is never re-checked.
For do...while, the only difference is that the body runs once before the very first condition check, then the same evaluate-and-repeat cycle applies. Because this all happens on the single JavaScript call stack, a while loop with a never-false condition will block the entire thread — in a browser this freezes the UI, and in Node.js it starves the event loop, so no timers, I/O callbacks, or promises can run until the loop somehow exits.
Common Mistakes
Mistake 1: Forgetting to update the loop variable
The single most common while-loop bug is writing a condition that depends on a variable you never change inside the body, creating an infinite loop:
let i = 0;
while (i < 5) {
console.log(i);
// forgot to increment i here
}
Since i is never reassigned, i < 5 is true forever and this would hang the program (never run this snippet as-is). The fix is to make sure something inside the loop body moves the condition toward becoming false:
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
Output:
0
1
2
3
4
Mistake 2: Using assignment (=) instead of comparison (===)
A single missing equals sign silently turns a comparison into an assignment. Because assignment expressions evaluate to the assigned value, this can make a loop appear to work by accident (or fail silently) instead of throwing an error:
let x = 5;
while (x = 0) {
console.log('This will never run');
}
console.log('Loop skipped because x was reassigned to 0');
Output:
Loop skipped because x was reassigned to 0
Here x = 0 assigns 0 to x and the expression evaluates to 0, which is falsy, so the body never runs at all — no error, no warning, just silently wrong behavior. Always double- and triple-check that a condition uses === (or another real comparison operator), not =:
let x = 5;
let attempts = 0;
while (x !== 0 && attempts < 3) {
console.log(`x is currently ${x}`);
x--;
attempts++;
}
console.log('Loop used a real comparison operator');
Output:
x is currently 5
x is currently 4
x is currently 3
Loop used a real comparison operator
Best Practices
- Reach for a
fororfor...ofloop when you know the number of iterations or are iterating a collection; reservewhilefor genuinely condition-driven repetition (queues, retries, parsing until a sentinel). - Always declare loop-control variables with
letorconst, nevervar, so scoping stays predictable. - Before writing the loop body, make sure you can point to the exact line that will eventually make the condition false.
- Use
do...whileonly when the body genuinely must run at least once before the first check makes sense (menus, input validation, retry-once logic). - Prefer
breakfor a clear early exit over adding extra boolean “flag” variables to the condition when possible — it’s usually easier to read. - For simple transformations over an existing array (mapping, filtering, searching), prefer array methods like
map,filter,find, orsomeover a manualwhileloop — they’re more declarative and less error-prone. - If a condition gets complex, extract it into a well-named variable or a small function so the loop reads like a sentence, e.g.
while (hasMoreItems()). - Add a safety counter or maximum-iteration guard when a loop’s exit depends on external or unpredictable data (like network responses), so a bug can’t hang the whole program.
Practice Exercises
- Exercise 1: Write a
whileloop that prints every even number from2to20(inclusive), each on its own line. - Exercise 2: Given the array
const letters = ['a', 'b', 'c', 'd'];, use awhileloop (not aforloop) to build and log a single string that joins the letters with hyphens, e.g."a-b-c-d". - Exercise 3: Use a
do...whileloop to simulate a countdown from a numbernof your choice down to0, printing each value, and print"Liftoff!"once the countdown reaches zero.
Summary
- A
whileloop checks its condition before each iteration and may run zero times if the condition starts false. - A
do...whileloop checks its condition after each iteration, so its body always runs at least once. - You are responsible for updating whatever the condition depends on — forgetting to do so causes an infinite loop that freezes the program.
- Use
breakto exit early andcontinueto skip to the next condition check without finishing the current iteration. - A stray
=instead of===in a condition is a classic, hard-to-spot bug because it’s valid syntax that silently changes behavior. - Prefer
whilefor condition-driven repetition and reach forfor,for...of, or array methods when the iteration count or collection is already known.
