The JavaScript For Loop, and Which Loop to Use

A classic for loop has three parts: for (let i = 0; i < arr.length; i++) { ... }. Use it when you need the index or a custom step. For plain values use for...of, for an object's keys use for...in or Object.entries, and use while when you do not know in advance how many rounds you need.

Which loop fits the job
LoopBest forCan break early?
for (let i = 0; i < n; i++)Counting, index access, stepping backwards or by 2Yes
for (const x of iterable)Values of arrays, strings, Maps, Sets, NodeListsYes
for (const key in obj)Keys of a plain object (includes inherited ones)Yes
while (condition)Repeat until something changes, unknown countYes
do { } while (condition)Same, but always runs at least onceYes
arr.forEach(fn)Side effects on every array itemNo (only by throwing)

Updated

Every loop on this page repeats code, but they differ in what they hand you each round, what they can loop over and how you get out. The runner below lets you point each loop at four kinds of data and watch the real output, which makes mistakes like for...in on an array or for...of on a plain object easy to spot.

Loop patterns to copy

Classic for, forwards, backwards and in steps

Change the start, the condition or the step to count any way you like.

const items = ["a", "b", "c", "d"];

for (let i = 0; i < items.length; i++) console.log(i, items[i]);  // 0 a ... 3 d
for (let i = items.length - 1; i >= 0; i--) console.log(items[i]); // d c b a
for (let i = 0; i < items.length; i += 2) console.log(items[i]);   // a c

for...of with the index

entries() pairs each value with its position, so you get both without a counter.

for (const [i, name] of ["Ana", "Bruno"].entries()) {
  console.log(`${i + 1}. ${name}`);
}
// 1. Ana
// 2. Bruno

while and do...while

do...while checks its condition after the body, so the body runs once even when the condition starts false.

let attempts = 0;
while (attempts < 3) {
  attempts++;
}

let n = 10;
do {
  console.log(n); // logs 10 once
  n++;
} while (n < 5);

Leaving nested loops with a label

break grid stops both loops as soon as the first match is found.

const grid = [[1, 2], [3, 42], [5, 6]];
let at = null;

grid: for (let r = 0; r < grid.length; r++) {
  for (let c = 0; c < grid[r].length; c++) {
    if (grid[r][c] === 42) {
      at = [r, c];
      break grid;
    }
  }
}
console.log(at); // [1, 1]

Awaiting each item in order

for...of pauses at each await. The same code inside forEach would start every request at once and not wait.

async function saveAll(rows) {
  for (const row of rows) {
    await fetch("/api/rows", { method: "POST", body: JSON.stringify(row) });
  }
}

Reading the three parts of a for loop

The first part runs once before anything else and usually creates the counter. The second is checked before every round, and the loop ends as soon as it is false. The third runs after each round, usually to move the counter on.

Any part can be left empty. for (;;) is a loop that only ends through break or return, which is occasionally useful for retry logic with a clear exit inside.

break, continue and labels

break leaves the innermost loop immediately. continue skips the rest of the current round and moves on to the next one. Both work in for, for...of, for...in, while and do...while, but not in a forEach callback, where return only ends that one call.

A label is a name followed by a colon in front of a statement. break label and continue label then target that outer statement, which saves you from managing a found flag across nested loops.

How it works

  1. Pick a loop and a kind of data. The page runs that loop for real in your browser.
  2. The output panel lists what the loop variable held on each round, or the error the combination throws.
  3. Turn on the break option to stop at the third round and see which loops support it.
  4. Copy any pattern from the examples further down.

Tips

Frequently asked questions

What is the difference between for...of and for...in?

for...of gives you values from anything iterable, such as the items of an array or the characters of a string. for...in gives you property names as strings, including inherited enumerable ones. On an array, for...in yields '0', '1', '2' rather than the items.

How do I break out of a forEach loop?

You cannot, except by throwing an error. Switch to for...of, which supports break, or to some, every, find or findIndex, which stop on their own once they have an answer.

How do I loop over an object in JavaScript?

Use for (const [key, value] of Object.entries(obj)). It covers only the object's own keys and gives you both parts. Using for...of directly on a plain object throws TypeError: obj is not iterable.

How do I exit two nested loops at once?

Put a label before the outer loop and use it with break: outer: for (...) { for (...) { if (found) break outer; } }. continue outer jumps to the next round of the outer loop instead.

How do I loop backwards?

Start at the last index and count down: for (let i = arr.length - 1; i >= 0; i--). This is also the safe way to remove items with splice while looping, since the positions you have yet to visit do not shift.

Related: JavaScript array methods, JavaScript objects guide, Async and fetch in JavaScript, JavaScript event listeners, JavaScript formatter.

Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.

More in Guides

We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.

Product

Who It's For

Features

Resources

Company

View Sitemap