Array.prototype.forEach()

Runs a function once for each array element, for its side effects only.

Signature
forEach(callbackFn)
forEach(callbackFn, thisArg)
  • Added in JavaScript ES5 (2009)

Parameters

ParameterTypeDescription
$callbackFnFunctionFunction run for each element, called with (element, index, array). Its return value is discarded.
$thisArgoptionalany= undefinedValue to use as this when executing callbackFn. Ignored by arrow functions.

Return value

undefinedAlways undefined — forEach() is not chainable.

Errors

Nothing of its own — throwing from callbackFn is the only way to abort the loop, and the error propagates to the caller.

forEach() exists for side effects: logging, pushing into an external structure, mutating objects in place. It returns undefined, so it is the end of a chain, never the middle of one. If you want a value back, that is a signal to use map(), filter() or reduce().

You cannot break out of it

There is no early exit. return inside the callback only ends that one invocation — the loop keeps going, which is the single most common surprise. break and continue are syntax errors there. When you need to stop early, use for...of, or pick a method whose job is to stop: find(), findIndex(), some(), every(). Throwing an exception works but should stay a last resort.

Async callbacks do not await

forEach() ignores what the callback returns, so an async callback produces a Promise that nobody waits on. The loop finishes immediately and the following line runs before any of the work does. Use for...of with await for sequential work, or Promise.all(arr.map(fn)) for parallel work.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Log or report each item in a collection during debugging
  • Attach a computed property to every object in an existing array
  • Push entries into a Map or Set built outside the loop
  • Fire off a side effect per element where no result is collected

Frequently asked questions

How do I break out of a forEach loop?

You can't — the only escape is throwing an exception. Use for...of with break, or switch to some() / every() / find() / findIndex(), which stop as soon as the callback tells them to.

What does forEach() return?

Always undefined, no matter what the callback returns. That makes it unchainable, so if you find yourself wanting to chain, use map() or filter() instead.

Should I use forEach() or for...of?

Use for...of when you need break, continue, or await; use forEach() when you want the index alongside the value and a self-contained callback. Speed is rarely the deciding factor: for...of does not avoid a per-element function call — it invokes the array iterator's next() on every pass — and engines typically make forEach() at least as fast.

More examples

return does not break the loop

Both print only 1 and 2, but for very different reasons. forEach still called the callback for 3, 4 and 5 and simply skipped the log; for...of actually stopped at 3. On a large array or an expensive predicate, that difference matters.

Example · javascript
const nums = [1, 2, 3, 4, 5];

nums.forEach((n) => {
  if (n > 2) return;
  console.log("forEach", n);
});

for (const n of nums) {
  if (n > 2) break;
  console.log("for...of", n);
}

Async callbacks are not awaited

The first log prints [] — forEach discarded the three Promises and moved on before any of them resolved. The map + Promise.all version prints ['done 1', 'done 2', 'done 3'], because those Promises are collected and awaited.

Example · javascript
const ids = [1, 2, 3];
const log = [];

ids.forEach(async (id) => {
  await null;
  log.push("done " + id);
});

console.log(log);
console.log(await Promise.all(ids.map(async (id) => "done " + id)));

Discussion

  • Be the first to comment on this lesson.