AlgoInsight

Free lesson · JavaScript Basic to Advance

Array Iteration: forEach, for...of, for...in

Easy5 min read

The Modern Way to Loop Through Arrays

The previous Topic covered the classic loops — for, while, do...while. They work for any kind of iteration. But for the most common case — looping over the elements of an array — modern JavaScript gives you cleaner, more declarative options.

const founders = ["Olena", "Nikhil", "Emeka", "Swati"];

// Classic for loop — still works, but verbose
for (let i = 0; i < founders.length; i++) {
  console.log(founders[i]);
}

// Modern: for...of
for (const founder of founders) {
  console.log(founder);
}

// Modern: forEach
founders.forEach(founder => console.log(founder));

All three loops produce identical output. The classic for loop gives you explicit index control. The modern alternatives — for...of and forEach — let you focus on the elements themselves without managing the index manually.

When I first learned JavaScript, I wrote classic for loops for everything. It took me months to switch to the modern patterns, and once I did, my code got noticeably cleaner. This Topic is meant to save you that learning curve.

for...of: The Cleanest Iteration

for...of iterates over the values of any iterable — arrays, strings, sets, maps, and more. It's the modern equivalent of "give me each element, one at a time."

const founders = ["Olena", "Nikhil", "Emeka"];

for (const founder of founders) {
  console.log(founder);
}

Notice three things about this loop:

for...of works on more than just arrays. It iterates over any object that implements JavaScript's iterable protocol:

// Iterating over a string (gives you each character)
for (const char of "Hello") {
  console.log(char);
}

// Iterating over a Set
const uniqueNumbers = new Set([1, 2, 3, 2, 1]);
for (const num of uniqueNumbers) {
  console.log(num);
}

This is the loop you'll use most often for arrays. When you just want to read each element and don't care about indices, for...of is the cleanest option.

When You Need the Index

If you do need the index along with the element, use entries() with for...of:

const founders = ["Olena", "Nikhil", "Emeka"];

for (const [index, founder] of founders.entries()) {
  console.log(`${index}: ${founder}`);
}

entries() returns pairs of [index, value]. The destructuring syntax [index, founder] pulls them apart. We cover destructuring in detail in Module 10 — for now, just know this is the modern way to get both the index and the value.

forEach: The Functional Approach

forEach is an array method that calls a function for each element. It's the most common "iterate over an array" pattern in modern JavaScript code.

const founders = ["Olena", "Nikhil", "Emeka"];

founders.forEach(founder => {
  console.log(founder);
});

// Shorter version when the body is one expression
founders.forEach(founder => console.log(founder));

The arrow function syntax founder => console.log(founder) is covered in detail in Module 5. For now: it's a compact way to write a function.

forEach also gives you the index as a second parameter, and the whole array as a third — most code only uses the first two:

const founders = ["Olena", "Nikhil", "Emeka"];

founders.forEach((founder, index) => {
  console.log(`${index}: ${founder}`);
});

The Critical Limitation of forEach

forEach has one important limitation that surprises everyone the first time: you cannot break out of it. The break keyword doesn't work inside forEach. There's no way to stop the iteration early.

const numbers = [1, 2, 3, 4, 5];

// This does NOT stop at 3 — forEach ignores the "early exit"
numbers.forEach(num => {
  if (num === 3) {
    return;   // returns from THIS callback, but the loop continues
  }
  console.log(num);
});
// Prints: 1, 2, 4, 5 (skipped 3, but didn't stop)

The return exits the callback function, but forEach keeps calling it for the remaining elements. This is by design — forEach is meant to visit every element. If you need to stop iteration early, use for...of or a regular for loop, where break works:

const numbers = [1, 2, 3, 4, 5];

for (const num of numbers) {
  if (num === 3) {
    break;   // actually stops here
  }
  console.log(num);
}
// Prints: 1, 2

This is a meaningful difference. When you're searching for something or stopping at a condition, prefer for...of. When you genuinely want to visit every element with no early exit, forEach is fine.

Interactive animation: Find the first expensive item - break cannot work inside forEach, but it works in for...of.

map, filter, reduce: Transformation Patterns

Modern JavaScript also gives you methods that aren't just iteration — they're transformations that produce new arrays or values.

map transforms each element and returns a new array:

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
console.log(doubled);   // [2, 4, 6, 8, 10]
console.log(numbers);   // [1, 2, 3, 4, 5] — unchanged

filter keeps elements that match a condition:

const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(n => n % 2 === 0);
console.log(evens);   // [2, 4]

reduce combines all elements into a single value:

const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((total, current) => total + current, 0);
console.log(sum);   // 15

These three methods — map, filter, reduce — are the backbone of functional-style array programming. Once you internalize them, you'll write significantly less imperative loop code. Many array transformations that take five lines of for loop code become one line of method chaining:

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const sumOfDoubledEvens = numbers
  .filter(n => n % 2 === 0)    // keep evens: [2, 4, 6, 8, 10]
  .map(n => n * 2)             // double them: [4, 8, 12, 16, 20]
  .reduce((sum, n) => sum + n, 0);   // sum: 60

console.log(sumOfDoubledEvens);

We'll cover these methods in detail in Module 5 (Functions Deep Dive) and Module 10 (Modern JavaScript). For now, know that they exist and that they're often the right tool when you find yourself reaching for a manual loop.

Choosing the Right Iteration

graph TD
    A[Need to iterate over an array] --> B{Do I need to stop early<br/>or skip iterations?}
    B -->|Yes| C[Use for...of with break]
    B -->|No, visit everything| D{Am I transforming<br/>into a new array?}
    D -->|Yes, one-to-one| E[Use map]
    D -->|Yes, filter elements| F[Use filter]
    D -->|Yes, combine into one value| G[Use reduce]
    D -->|No, just side effects<br/>like logging| H[Use forEach or for...of]

    style C fill:#7c3aed,color:#fff
    style E fill:#10b981,color:#fff
    style F fill:#10b981,color:#fff
    style G fill:#10b981,color:#fff
    style H fill:#3b82f6,color:#fff
This diagram shows how to choose the right iteration method. Start by asking whether you need to stop early or skip iterations. If yes, use for...of with break. If no, ask whether you're transforming the array into a new one. If you're producing one new element per input element, use map. If you're keeping only some elements, use filter. If you're combining everything into a single value, use reduce. If you're just visiting each element for side effects like logging or updating an external counter, use forEach or for...of.

Common Pitfalls

Warning: The iteration traps.

Using forEach when you need to break. forEach cannot be stopped early. If you find yourself trying to return from a forEach to "exit," switch to for...of.

Forgetting that map and filter return new arrays. They don't modify the original. If you need to update the source array in place, use a regular loop. (But generally, prefer immutable operations — it makes code easier to reason about.)

Using for...in for arrays. for...in iterates over object property keys, which on arrays gives you indices as strings. It's almost never what you want. Use for...of for array values or entries() for index-value pairs.

Interactive animation: for...of beside for...in on the same array - for...in yields the indices as string keys, not the values.

Why This Matters in Interviews

Interview: Modern array methods are expected fluency. An interviewer who watches you write for (let i = 0; i < arr.length; i++) for every iteration sees a candidate stuck in pre-2015 JavaScript. The same problem written with map, filter, or reduce signals familiarity with modern idioms.

The exception: when index manipulation is genuinely part of the problem, classic loops are appropriate. Two-pointer techniques, sliding window patterns, complex traversal logic — these are clearer with explicit indices. Use modern methods when they help; reach for classic loops when the problem actually needs index control.

Topic 4.6 — Interview Lens: Control Flow and Iteration Patterns — covers the interview treatment of these choices.

Try It

Exercise: Given this array, solve each problem using the most appropriate iteration method:

const users = [
  { name: "Olena", age: 35, role: "Product" },
  { name: "Nikhil", age: 32, role: "Engineering" },
  { name: "Emeka", age: 31, role: "Data" },
  { name: "Arun", age: 24, role: "Engineering" },
  { name: "Swati", age: 38, role: "Leadership" }
];
  1. Print each user's name (just side effects)
  2. Create a new array of just the names
  3. Get only the users whose role is "Engineering"
  4. Calculate the sum of all ages
  5. Find the first user under 30

For each one, decide whether to use forEach, map, filter, reduce, or for...of with break. The choice should be based on what you're doing, not just personal preference. Once you can match the right method to each problem instantly, you've internalized modern array iteration.

Back to JavaScript Basic to Advance