Free lesson · JavaScript Basic to Advance
Array Iteration: forEach, for...of, for...in
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:
- No index management. You're not tracking
iand incrementing it. - The variable inside (
founder) holds the element itself, not an index. - It uses
constbecause you're not reassigning the variable — each iteration creates a fresh binding.
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
forEachwhen you need to break.forEachcannot be stopped early. If you find yourself trying to return from aforEachto "exit," switch tofor...of.Forgetting that
mapandfilterreturn 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...infor arrays.for...initerates over object property keys, which on arrays gives you indices as strings. It's almost never what you want. Usefor...offor array values orentries()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 withmap,filter, orreducesignals 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" } ];
- Print each user's name (just side effects)
- Create a new array of just the names
- Get only the users whose role is "Engineering"
- Calculate the sum of all ages
- Find the first user under 30
For each one, decide whether to use
forEach,map,filter,reduce, orfor...ofwithbreak. 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.