Knowledge Base/concepts/JavaScript while Loops

JavaScript while Loops

JavaScript while loops are for repetition controlled by a condition, not by a tidy little counter in the loop header. They are best when the code should keep going until something changes: a queue becomes empty, a value becomes valid, a retry limit is reached, or a search finally finds what it came for.

Basic syntax

A while loop checks its condition before each run of the loop body:

while (condition) {
  // Repeat this while the condition is true.
}

Here is a small countdown:

let timer = 3;

while (timer > 0) {
  console.log(timer);
  timer--;
}

// 3
// 2
// 1

When timer becomes 0, the condition timer > 0 is false, so the loop stops.

The three moving parts

A safe while loop usually has three pieces:

  1. State that exists before the loop
  2. A condition that checks that state
  3. An update inside the loop that can eventually make the condition false
let count = 1;
const values = [];

while (count <= 3) {
  values.push(count);
  count++;
}

console.log(values); // [1, 2, 3]

The update is not decorative. It is the escape route.

If you cannot point to the state that changes, the loop is suspicious. Sometimes that state is a counter. Sometimes it is an array getting shorter, a string being consumed, or a flag being flipped.

while versus for

Use a for loop when the loop shape is a clear count:

for (let i = 0; i < 5; i++) {
  console.log(i);
}

Use a while loop when the stopping condition is the main idea:

while (pendingJobs.length > 0) {
  const job = pendingJobs.shift();
  runJob(job);
}

That loop does not care whether there are three jobs or three hundred. It keeps going while the queue has work.

The JavaScript for Loops guide covers counters, indexes, and off-by-one boundaries. while is a different shape: condition first, count second.

Counting with a while loop

You can count with while, but you have to manage the counter yourself:

let n = 1;
let total = 0;

while (n <= 5) {
  total += n;
  n++;
}

console.log(total); // 15

This works, but a for loop would keep the counter setup and update together:

let total = 0;

for (let n = 1; n <= 5; n++) {
  total += n;
}

console.log(total); // 15

The result is the same. The readability is different. If the counter is the structure, for usually wins. If the condition is the structure, while earns its keep.

The infinite-loop failure mode

This loop never stops:

let count = 1;

while (count <= 5) {
  console.log(count);
}

count starts at 1, and nothing inside the loop changes it. The condition stays true forever. In a browser, that can freeze the page until the tab gives up on you. Lovely experience, very artisanal.

Fix it by moving the state toward the stopping condition:

let count = 1;

while (count <= 5) {
  console.log(count);
  count++;
}

When a while loop misbehaves, inspect the update first. Ask: what changes during each pass, and how does that change make the condition false?

Using while with changing data

while works well when the data itself changes as you process it:

const pending = ["lint", "test", "deploy"];
const completed = [];

while (pending.length > 0) {
  const task = pending.shift();
  completed.push(task);
}

console.log(completed); // ["lint", "test", "deploy"]
console.log(pending); // []

The loop condition depends on pending.length. Each iteration removes one task, so the condition eventually becomes false.

This pattern is common with queues, retry lists, paginated data, parser tokens, and other "keep going until the source is empty" problems.

If you should preserve the original array, use an index instead:

const pending = ["lint", "test", "deploy"];
const completed = [];
let index = 0;

while (index < pending.length) {
  completed.push(pending[index]);
  index++;
}

console.log(completed); // ["lint", "test", "deploy"]
console.log(pending); // ["lint", "test", "deploy"]

That version processes the values without removing them.

break and continue

break exits a while loop immediately:

const names = ["Ada", "Grace", "Linus", "Brendan"];
let index = 0;
let firstLongName = "";

while (index < names.length) {
  const name = names[index];

  if (name.length > 5) {
    firstLongName = name;
    break;
  }

  index++;
}

console.log(firstLongName); // "Brendan"

continue skips to the next condition check. That means your update still has to happen before the skip when the update is needed:

const scores = [82, -1, 94, 120, 75];
const validScores = [];
let index = 0;

while (index < scores.length) {
  const score = scores[index];
  index++;

  if (score < 0 || score > 100) {
    continue;
  }

  validScores.push(score);
}

console.log(validScores); // [82, 94, 75]

Moving index++ after the invalid-score check would create a bug. If the score is invalid, continue would skip the update, and the loop would inspect the same invalid value forever. That is one of those bugs that looks small until your browser fan starts making management decisions.

When the condition starts false

A while loop might run zero times:

let attemptsLeft = 0;

while (attemptsLeft > 0) {
  console.log("Trying again");
  attemptsLeft--;
}

Nothing logs because the condition is false before the first body run.

That is often exactly what you want. If there are no attempts left, do not try. If there are no items in a queue, do not process an item.

If you truly need the body to run at least once, JavaScript has do...while:

let answer = "";

do {
  answer = getNextAnswer();
} while (answer === "");

Use it deliberately. Most loops are easier to reason about when the condition appears before the body.

Do not busy-wait

A while loop is synchronous. It does not politely give the rest of JavaScript a turn while it runs.

This blocks the thread:

const start = Date.now();

while (Date.now() - start < 1000) {
  // Block everything for one second.
}

console.log("done");

In a browser, that means rendering, input handling, timers, and promise callbacks all wait. A while loop is not a timer. It is repeated synchronous work.

Use a timer, a promise, or an async API when you need waiting behavior. The Tasks vs Microtasks guide explains why queued callbacks cannot run while the current synchronous code is still occupying the stack.

Key Takeaways

  • Use JavaScript while loops when a condition, not a fixed count, controls repetition.
  • A safe while loop needs changing state that can eventually make the condition false.
  • Put required counter updates before continue, or the loop can get stuck on the same value.
  • A while loop may run zero times because the condition is checked before the body.
  • Do not use while to wait for time to pass. It blocks the thread instead of scheduling work.
Share this article:
javascriptfundamentalsloopscontrol-flow