JavaScript Loops

Pick the right loop in JavaScript with for, while, for-of, for-in, and array methods.

TL;DR

  1. 01Use for and while when you need full counter control.
  2. 02Use for-of for arrays and for-in for object keys.
  3. 03Use array methods like map and filter for transformations.

Tips

  1. 01Reach for array methods like map and filter first for transformations, since they read more clearly than equivalent for loops.
  2. 02Use for...of instead of for...in on arrays, since for...in iterates keys as strings and can pick up inherited enumerable properties.

Warnings

  1. 01Do not modify an array with splice or push while looping, since this skips items and causes subtle bugs.
  2. 02Using await inside a forEach callback silently fails to pause, since forEach ignores returned promises and runs callbacks without waiting.

For and While

  • JavaScript gives you three ways to loop with a condition, and each one fits a different shape of problem.
    for (let i = 0; i < 5; i++) {
      console.log(i);
    }
    
  • Use a while loop when you do not know how many iterations are needed.
    let n = 0;
    while (n < 3) {
      console.log(n);
      n++;
    }
    
  • Use do...while when the body must run at least once before checking.
    let i = 0;
    do {
      console.log(i);
      i++;
    } while (i < 3);
    
  • Always make sure the loop condition can become false to avoid infinite loops.
  • Use break to exit a loop early and continue to skip an iteration.

For-of for Arrays

  • No index, no counter, no off-by-one errors — for...of hands you each value directly.
    const nums = [10, 20, 30];
    for (const n of nums) console.log(n);
    
  • Works on strings, Sets, Maps, NodeLists, and any other iterable.
    for (const char of "Hi") console.log(char);
    
  • Destructure inside the loop for cleaner access to object properties.
    for (const { name } of users) console.log(name);
    
  • This is the cleanest loop for most array iteration needs in modern code.
  • Use entries() if you also need the index alongside the value.

For-in for Objects

  • for...in walks property names, not values — a distinction that trips up developers coming from for...of.
    const user = { name: 'Ada', age: 30 };
    for (const key in user) {
      console.log(`${key}: ${user[key]}`);
    }
    
  • Use bracket notation obj[key] to read each value during the loop.
  • Avoid using for...in on arrays, since it iterates keys, not values.
  • Add a hasOwnProperty check to skip inherited properties when needed.
  • Prefer Object.keys() or Object.entries() for more predictable iteration.

Async Loops

  • forEach silently ignores every promise its callback returns, making it the most common source of broken async loops.
    async function processAll(ids) {
      for (const id of ids) {
        const result = await fetchItem(id);
        console.log(result);
      }
    }
    
  • Avoid forEach with await — it does not wait for each async callback to complete.
    // Broken: forEach ignores returned promises
    items.forEach(async item => {
      await save(item); // fires but does not block
    });
    
  • Use Promise.all() with map() to run all async operations in parallel instead.
    const results = await Promise.all(ids.map(id => fetchItem(id)));
    
  • Use for await...of to consume an async iterable like a stream or generator.
    for await (const chunk of readStream()) {
      console.log(chunk);
    }
    
  • Sequential for...of with await is slower but safe when order matters between items.

Nested and Control

  • A plain break only escapes the innermost loop — labeled breaks are the only way out of nested ones.
    for (let i = 0; i < 2; i++) {
      for (let j = 0; j < 3; j++) {
        console.log(`${i},${j}`);
      }
    }
    
  • Use labeled break to exit out of multiple levels of nested loops.
    outer: for (let i = 0; i < 3; i++) {
      for (let j = 0; j < 3; j++) {
        if (i === 1) break outer;
      }
    }
    
  • Use break to exit a search loop as soon as you find what you need.
  • Use return inside array methods like forEach to skip an iteration.
  • Cache array.length outside hot for loops for a small performance gain.

FAQ