How JavaScript Loops Work (for, while)

You’ve used for loops in earlier guides — this one goes deeper, covering while loops, do…while loops, and the practical rule for choosing between them.

If you’ve worked through our guides on arrays and if/else statements, you’ve likely already written a basic for loop. This guide covers the full picture: for, while, and do…while, and when each one actually fits better.

The for Loop, Recap

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

According to MDN's guide to loops and iteration, a for loop bundles three things — an initializer, a condition, and an update step — directly into its parentheses, making it self-contained and easy to scan at a glance.

The while Loop

A while loop checks its condition before each iteration, but doesn't bundle initialization or updates into its syntax the way a for loop does:

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

You're responsible for creating the counter beforehand and updating it yourself inside the loop body — forgetting the increment is a common beginner mistake that produces an infinite loop, since the condition never becomes false.

The do...while Loop

This variant checks its condition after running the loop body, guaranteeing the code runs at least once even if the condition is false from the start:

let i = 10;
do {
  console.log(i);
  i++;
} while (i < 5);
// Still prints 10 once, even though the condition is already false

This is genuinely useful for situations like asking for user input, where you want to prompt at least one time before checking whether to prompt again.

How to Actually Choose Between Them

According to a comparison from Built In's guide to for vs. while loops, the practical rule is simple: use a for loop when you know the number of iterations ahead of time (like looping through an array), and use a while loop when you don't — for example, when a loop should continue until some external condition changes, like a game running until the player loses or wins.

  • for — iterating over an array, or any known, fixed number of repetitions.
  • while — repeating until a condition becomes false, when you don't know in advance how many iterations that will take.
  • do...while — same as while, but guarantees at least one run before checking the condition.

for...of and for...in

Beyond the three core loop types, JavaScript offers two specialized variants for looping through collections. for...of loops through the values of an array (or other iterable):

const fruits = ["apple", "banana"];
for (const fruit of fruits) {
  console.log(fruit);
}

for...in loops through the keys of an object instead of array values — worth knowing exists, but easy to confuse with for...of, so double-check which one a piece of code is actually using if the output looks unexpected.

Controlling a Loop With break and continue

Two keywords let you control a loop's flow beyond just running every iteration to completion. As freeCodeCamp's guide to JavaScript loops explains, break exits the loop immediately, while continue skips just the current iteration and moves to the next one:

for (let i = 0; i < 10; i++) {
  if (i === 5) break;      // stops the loop entirely at 5
  if (i % 2 === 0) continue; // skips even numbers, keeps looping
  console.log(i);
}
// Output: 1, 3

A simple way to remember the difference: break means "stop everything," while continue means "skip just this one and keep going."

Nested Loops

A loop can contain another loop inside it — useful for grid-like or table-like data:

for (let row = 0; row < 3; row++) {
  for (let col = 0; col < 3; col++) {
    console.log(`(${row}, ${col})`);
  }
}

The inner loop completes all of its iterations before the outer loop advances to its next value. Nested loops can get confusing quickly, so it's fine to treat this as an advanced pattern to revisit once single loops feel completely natural.

A Common Mistake: Off-by-One Errors

One of the most frequent loop bugs is looping one time too many or too few — commonly called an off-by-one error. Using < instead of <= (or vice versa) in your condition is the usual culprit. When a loop's output is off by exactly one item, this comparison operator is usually the first place worth checking.

A Practical Example: Combining Loop Types

Here's a scenario where a while loop genuinely fits better than a for loop — validating input until it meets a condition, something a for loop's fixed structure doesn't handle as naturally:

let attempts = 0;
let success = false;

while (!success && attempts < 3) {
  attempts++;
  // simulate a check; in real code this might be user input validation
  success = attempts === 2;
  console.log(`Attempt ${attempts}: ${success ? "success" : "failed"}`);
}

Since we don't know in advance which attempt will succeed, a while loop — driven by a condition rather than a fixed count — is the more natural fit here than trying to force a for loop to do the exact same job artificially.

Common Questions

Can every for loop be rewritten as a while loop? Yes — the two are functionally equivalent, just organized differently. The choice comes down to readability for your specific situation, not capability.

What causes an infinite loop? The condition never becomes false — usually because the counter isn't being updated correctly, or the update step was left out entirely. If your program hangs or your browser tab freezes, check your loop's update logic first, since that's the cause in the overwhelming majority of cases.

Is do...while commonly used in practice? Less often than for and while, since the "run at least once" behavior is a fairly specific need. It's worth knowing it exists, but you'll reach for plain while loops far more frequently.

Should I always use for...of instead of a traditional for loop? For simply iterating through values, for...of is usually cleaner and less error-prone, since it removes the need to manage an index manually. Stick with a traditional for loop when you specifically need the index itself for something in the loop body.

Iterating Objects with Object.entries()

Looping through an object's key-value pairs is a common enough task to be worth a dedicated pattern. Combining for...of with Object.entries() lets you loop through both the key and value together in one line:

const scores = { alice: 90, bob: 85 };
for (const [name, score] of Object.entries(scores)) {
  console.log(`${name}: ${score}`);
}

This is a genuinely common pattern once you start working with objects — a topic covered in more depth in the next guide in this series.

Looping Through Strings

Strings can be looped through just like arrays, since each character has a position:

const word = "hello";
for (const letter of word) {
  console.log(letter);
}

This is useful whenever you need to examine or process text character by character — checking for a specific character, reversing a string manually, or counting occurrences of a letter are all common exercises that rely on exactly this pattern.

Building a Small Program With Loops

Here's a slightly larger example tying several concepts together — counting how many numbers in a list are above a threshold:

const scores = [55, 82, 91, 47, 76, 88];
let passingCount = 0;

for (const score of scores) {
  if (score >= 70) {
    passingCount++;
  }
}

console.log(`${passingCount} scores passed.`);

This combines a for...of loop with an if statement and a running counter — a genuinely common pattern once you start writing anything beyond a single isolated loop, and one you'll reuse constantly across very different kinds of problems.

Loop Performance: A Brief Note

For everyday scripts, the performance difference between loop types is negligible and not worth worrying about. It only becomes a genuine consideration when processing very large datasets, at which point array-specific methods (like map() or filter(), covered in a future guide) sometimes offer both cleaner code and better performance than a manually written loop. As a beginner, prioritize writing loops you understand clearly over micro-optimizing something that rarely matters in practice.

Quick-Reference Guide

  • for — known number of iterations, self-contained syntax.
  • while — unknown number of iterations, checked before each run.
  • do...while — like while, but always runs at least once.
  • for...of / for...in — specialized loops for array values and object keys.

Conclusion

All JavaScript loops solve the same basic problem — repeating code — but picking the right one for your situation makes the intent of your code clearer to anyone reading it later, including yourself weeks or months down the line. Default to for loops when you know the count, while loops when you don't, and reach for do...while only when you specifically need that first guaranteed run before checking anything else.

In the next guide in this series, we'll cover JavaScript objects — a different way of organizing data, using named properties instead of array positions.

Explore More JavaScript Basics Guides →

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top