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 any let/const declared directly inside the body on that pass.
  • After the body finishes (or a continue is hit), control jumps back to step 1 and re-evaluates the condition.
  • A break statement 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 for or for...of loop when you know the number of iterations or are iterating a collection; reserve while for genuinely condition-driven repetition (queues, retries, parsing until a sentinel).
  • Always declare loop-control variables with let or const, never var, 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...while only when the body genuinely must run at least once before the first check makes sense (menus, input validation, retry-once logic).
  • Prefer break for 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, or some over a manual while loop — 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 while loop that prints every even number from 2 to 20 (inclusive), each on its own line.
  • Exercise 2: Given the array const letters = ['a', 'b', 'c', 'd'];, use a while loop (not a for loop) to build and log a single string that joins the letters with hyphens, e.g. "a-b-c-d".
  • Exercise 3: Use a do...while loop to simulate a countdown from a number n of your choice down to 0, printing each value, and print "Liftoff!" once the countdown reaches zero.

Summary

  • A while loop checks its condition before each iteration and may run zero times if the condition starts false.
  • A do...while loop 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 break to exit early and continue to 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 while for condition-driven repetition and reach for for, for...of, or array methods when the iteration count or collection is already known.