JavaScript forEach で配列要素に処理を実行

JavaScript の配列 forEach(Array.prototype.forEach)は、配列の各要素に対してコールバックをインデックス順に1回ずつ実行します。JavaScript forEach ループは、ロギング、DOM 更新、外側の変数更新のような副作用が目的で、breakawait が不要なときに使います。戻り値は undefined なので、変換(map)や途中で止められる検索(find, some)には向きません。制御フローが必要なら for...of ループを選びます。

配列を反復する JavaScript forEach の例

出力:

ここに出力が表示されます...

出力:

0: 赤
1: 緑
2: 青

この例の仕組み

  1. colors は3つの文字列を持つ配列です。
  2. forEach は要素ごとにアロー関数を1回呼び出し、現在の要素と0始まりのインデックスを引数として渡します。
  3. コールバックは位置と色のペアをログ出力します。forEach は昇順インデックスで処理し、疎配列の空スロットはスキップします。

forEach でよくある落とし穴

forEach を async/await と一緒に使う:

Wrong:

const urls = ["https://example.com/a", "https://example.com/b"];

urls.forEach(async (url) => {
  await fetch(url);
});
console.log("完了"); // すぐ実行される

Right:

for (const url of urls) {
  await fetch(url);
}

forEach はコールバックが返した Promise を待機しません。順番に await したいなら for...of、並列処理なら await Promise.all(urls.map((url) => fetch(url))) を使います。

forEach を途中で抜けようとする:

Wrong:

const items = ["a", "b", "c"];
const target = "b";

items.forEach((item) => {
  if (item === target) break; // 構文エラー
});

Right:

const found = items.find((item) => item === target);

forEach は早期終了できません。短絡評価の検索には find/somebreak が必要なら for...of を使います。

forEach vs map vs for…of

特性forEachmapfor...of
戻り値undefined新しい配列—(ループ)
早期終了不可不可break / return
await との相性不可Promise.all と併用
最適な用途副作用変換制御フロー

副作用だけが目的で、早期終了と await が不要なら forEach を使います。結果として変換済みの配列が必要なら mapbreakcontinue、逐次 await が必要なら for...of を使います。

FAQ

JavaScript forEach は途中で抜けられますか?

できません。forEach はすべての要素に対してコールバックを実行します。例外を投げれば停止できますが、これはアンチパターンです。break が必要なら for...of、短絡評価の検索なら find/some/every を使ってください。

forEach は元の配列を変更しますか?

forEach 自体は配列を変更しません。コールバックには参照が渡されるため、オブジェクト要素はその場で変更できます。一方、数値や文字列のようなプリミティブ値は値渡しなので、コールバック引数経由では変更できません。

forEach と map の違いは何ですか?

forEachundefined を返し、副作用向けです。map はコールバックの戻り値から新しい配列を作って返します。データ変換が目的なら map、ログ出力や DOM 更新のような処理実行が目的なら forEach を使います。