Iterating Arrays
Visiting every element in an array is one of the most common things you’ll do in JavaScript, and the language gives you several ways to do it. Each approach makes a different trade-off between control, readability, and the kind of data you have access to inside the loop. This page compares the classic for loop, the modern for...of loop, the forEach method, and the entries() iterator so you can reach for the right one without guessing.
The classic for loop
The C-style for loop manages a counter by hand: an initializer, a condition, and an update expression. It gives you maximum control — you can step backwards, skip elements, mutate the index, or stop early — at the cost of being verbose and easy to get wrong by one.
const colors = ["red", "green", "blue"];
for (let i = 0; i < colors.length; i++) {
console.log(`${i}: ${colors[i]}`);
}
Output:
0: red
1: green
2: blue
Use it when you genuinely need the numeric index, want to iterate in reverse, or need to skip ahead. For straightforward front-to-back iteration, the options below read better.
for…of
for...of (ES2015) loops over the values of any iterable — arrays, strings, Map, Set, arguments, NodeLists, and more. There’s no counter to manage and no length to compare against, so it’s the cleanest choice when you only care about the elements themselves.
const colors = ["red", "green", "blue"];
for (const color of colors) {
console.log(color);
}
Output:
red
green
blue
Crucially, for...of supports break, continue, and even return inside a function, so you can short-circuit the moment you’ve found what you need.
const nums = [4, 8, 15, 16, 23, 42];
for (const n of nums) {
if (n > 15) break;
console.log(n);
}
Output:
4
8
15
Don’t confuse
for...ofwithfor...in.for...initerates keys (property names as strings) and walks inherited enumerable properties, which makes it the wrong tool for arrays. Usefor...offor values andfor...inonly for plain objects.
forEach
Array.prototype.forEach calls a callback once per element, passing the value, the index, and the array itself. It’s expressive and pairs naturally with arrow functions, but it comes with one important limitation.
const colors = ["red", "green", "blue"];
colors.forEach((color, index) => {
console.log(`${index} → ${color}`);
});
Output:
0 → red
1 → green
2 → blue
The catch: you cannot break or continue out of forEach. A return inside the callback only exits the current iteration (like continue), and there’s no way to stop early. If you need to bail out, use for...of, or switch to a method built for the job — some()/every() for early-exit checks, or find() to locate one item.
const nums = [1, 2, 3, 4, 5];
// This does NOT stop at 3 — return only skips one pass.
nums.forEach((n) => {
if (n === 3) return;
console.log(n);
});
Output:
1
2
4
5
Another subtlety: forEach skips holes in sparse arrays and always returns undefined, so you can’t chain it.
entries() for index and value
When you want both the index and the value with the clean syntax of for...of, combine it with entries(). The method returns an iterator of [index, value] pairs, which you destructure right in the loop header.
const colors = ["red", "green", "blue"];
for (const [index, color] of colors.entries()) {
console.log(`${index}: ${color}`);
}
Output:
0: red
1: green
2: blue
This gives you the index without managing a counter and still lets you break and continue. Its siblings keys() (indexes only) and values() (values only, the default for for...of) round out the trio.
Choosing a loop
| Construct | Gives you | Can break early? | Best for |
|---|---|---|---|
for | Index (manual) | Yes | Reverse, skipping, fine control |
for...of | Value | Yes | Simple value iteration on any iterable |
for...of + entries() | Index + value | Yes | Need both, want early exit |
forEach | Value, index, array | No | Side effects on every element |
Best Practices
- Prefer
for...offor reading values — it’s the most readable option and works on every iterable, not just arrays. - Reach for
for...ofwithentries()when you need the index, rather than a manual counter. - Use a classic
forloop only when you need reverse order, index arithmetic, or to skip elements. - Choose
forEachfor pure side effects (logging, DOM updates) where you never need to stop early. - If you might bail out mid-loop, avoid
forEach— itsreturncannot break; usefor...of,some(), orfind(). - Don’t use
for...inon arrays; it iterates keys as strings and includes inherited properties. - When you’re transforming data rather than just visiting it, prefer
map,filter, orreduceover a loop that pushes into a new array.