Iterator.prototype.forEach()
Run a callback for every value of an iterator and return undefined.
forEach(callbackFn)- Added in JavaScript ES2025 (Baseline March 2025)
Parameters
| Parameter | Type | Description |
|---|---|---|
$callbackFn | Function | Called once for each element as callbackFn(element, index). element is the current value and index is its zero-based position in the iteration. Its return value is ignored. |
Return value
undefinedundefined. The callback's return values are discarded.
Errors
Throws a TypeError if callbackFn is not callable, or if called on a value that is not an object; it does not terminate on an infinite iterator.
forEach() is a terminal, eager operation: unlike map() and filter() it does not return a helper, it drains the iterator on the spot and returns undefined. It exists for side effects — logging, writing, dispatching — at the end of a chain.
When to reach for it
- Finishing a helper chain with an action rather than a value, without breaking the fluent style.
- Consuming an iterator you already have when you also want the element index.
What trips people up
There is no way out. break, continue and return inside the callback do not stop the loop — return only ends that one invocation. The only exits are throwing, or using some()/find(), which short-circuit by design. That also means it never terminates on an infinite iterator.
It is not await-aware either: an async callback returns a promise that forEach() discards, so the loop races ahead without waiting. Use for await...of, or a plain for...of loop, when order and awaiting matter.
In most cases a for...of loop over the iterator is equally clear, supports break, and reads better — reserve forEach() for the tail of a chain.
Example
When to use it
- Log or dispatch every survivor at the end of a filter chain
- Walk Map entries with access to the position index
- Drain a bounded generator purely for its side effects
Frequently asked questions
How do I break out of forEach() on an iterator?
You cannot — return inside the callback only ends that invocation. Use a for...of loop with break, or a short-circuiting helper such as some() or find() if the goal is to stop at the first match. Throwing an exception also exits, but it is a poor substitute for control flow.
Does forEach() work with async callbacks?
Not usefully. It ignores the promise the callback returns, so every invocation starts without waiting for the previous one and the method returns before any of them finish. Use for await...of over the iterator, or collect promises with map() and toArray() and pass them to Promise.all().
Should I use forEach() or a for...of loop?
Use for...of by default — it supports break, continue and await, and it reads more naturally. forEach() earns its place at the end of a helper chain, where switching to a loop would mean breaking the fluent expression apart.
More examples
The index counts what forEach sees
The index restarts at 0 for the filtered stream, because each helper numbers the elements it receives. Do not expect it to match positions in the original array.
const nums = [10, 11, 12, 13, 14].values();
nums
.filter((n) => n % 2 === 0)
.forEach((n, i) => console.log(`#${i} -> ${n}`));
// #0 -> 10
// #1 -> 12
// #2 -> 14Why you cannot break out
forEach logs 1, 2 and 4 — the return skipped only the third invocation. The for...of loop logs 1 and 2 and then genuinely stops, leaving the iterator unconsumed.
[1, 2, 3, 4].values().forEach((n) => {
if (n === 3) return; // skips this call only
console.log("forEach saw", n);
});
for (const n of [1, 2, 3, 4].values()) {
if (n === 3) break; // actually stops
console.log("for-of saw", n);
}
Discussion