【2026年8月最新】JavaScript forEach文の使い方まとめ|配列の繰り返し処理・for文やmapとの違い
この記事の内容
「JavaScriptのforEachで配列をループさせたいけど、for文と何が違うの?途中でbreakできないって本当?」——検索でこの記事にたどり着いた方は、そんな疑問を抱えているはずです。
forEach()は、JavaScriptで配列の各要素に対して処理を行う際に最もよく使われるメソッドの一つです。書き方自体はシンプルですが、「途中で処理を止められない」「非同期処理と組み合わせると意図通りに動かない」といった、知らないとハマりやすい特性がいくつかあります。
この記事では、forEach()の基本的な使い方から、for文・map()との違い、非同期処理との組み合わせで起きる典型的な事故、そしてClaude CodeのようなAIコーディングツールを使ったコードレビューの活用方法まで整理します。
この記事を最後まで読むと、次の6つが明確になります。
01 OVERVIEW forEach()の基本構文と動作 配列の要素を1つずつ処理するための定番メソッド
forEach()は、配列(Array)が持つメソッドの一つで、配列の各要素に対して、指定した処理(コールバック関数)を順番に実行します。基本構文は以下の通りです。
array.forEach(function(value, index, array) {
// 各要素に対して行いたい処理
});
// アロー関数を使った書き方(実務ではこちらが主流)
array.forEach((value, index, array) => {
// 各要素に対して行いたい処理
});
📚 用語解説
コールバック関数:別の関数(ここではforEach)に引数として渡され、その関数の内部から呼び出される関数のこと。forEachでは配列の要素の数だけ、このコールバック関数が繰り返し実行されます。
具体的な例を見てみましょう。
const fruits = ['りんご', 'バナナ', 'みかん'];
fruits.forEach((fruit) => {
console.log(fruit);
});
// 出力:
// りんご
// バナナ
// みかん
1-1. forEachが向いている場面
forEachは、「配列の全要素に対して、何らかの処理(表示・保存・送信など)を行いたいが、新しい配列は必要ない」という場面に向いています。ループのカウンタ管理や終了条件の記述が不要なため、for文よりも簡潔に書けるのが最大のメリットです。
「配列の要素を1つずつ使って何かする(副作用のある処理)だけで、新しい配列に変換する必要がない」場合はforEachが最適です。変換結果を新しい配列として受け取りたい場合は、後述するmap()を検討してください。
1-2. forEachの対応状況と歴史的な背景
forEach()は、2009年に標準化されたECMAScript 5(ES5)で導入された配列メソッドです。導入からすでに15年以上が経過しており、現在使われているほぼすべてのブラウザ・Node.js環境で問題なく利用できます。互換性を心配する必要がない、枯れた機能と言えます。
📚 用語解説
ECMAScript(ES):JavaScriptの標準仕様を定めた規格。ES5、ES6(ES2015)のようにバージョンで呼ばれ、新しい構文や機能はこの規格の改訂を通じて追加されます。forEachはES5、後述するmap()やfilter()も同じくES5で追加されました。
それ以前のJavaScriptでは、配列をループするにはfor文を使うしかありませんでした。forEachの登場によって、「カウンタ変数の初期化・終了条件・インクリメント」を毎回書く必要がなくなり、コードの見通しが大きく改善されました。
02 CALLBACK ARGS コールバック関数の3つの引数 value・index・arrayの役割を正しく理解する
forEachのコールバック関数は、最大で3つの引数を受け取ることができます。
| 引数 | 内容 |
|---|---|
| 第1引数(value) | 現在処理中の要素そのものの値 |
| 第2引数(index) | 現在処理中の要素の配列内での位置(0から始まる添字) |
| 第3引数(array) | forEachの処理対象になっている配列全体 |
const fruits = ['りんご', 'バナナ', 'みかん'];
fruits.forEach((fruit, index, array) => {
console.log(`${index}番目: ${fruit}(配列の長さ: ${array.length})`);
});
// 出力:
// 0番目: りんご(配列の長さ: 3)
// 1番目: バナナ(配列の長さ: 3)
// 2番目: みかん(配列の長さ: 3)
第2引数のindexは、「何番目の要素を処理しているか」を知りたいときに便利です。例えば「最初の要素だけ特別な処理をしたい」といったケースで活用できます。
fruits.forEach((fruit, index) => {
if (index === 0) {
console.log(`最初の果物は${fruit}です`);
} else {
console.log(fruit);
}
});
📚 用語解説
添字(インデックス):配列の中で、それぞれの要素が何番目に位置するかを表す番号。JavaScriptを含む多くのプログラミング言語では0番目から数え始めるため、3つの要素がある配列の添字は0, 1, 2になります。
2-1. 第3引数(array)が使われる場面
第3引数のarrayは、コールバック関数の外側で配列を参照する変数を用意しなくても、「今処理している配列そのもの」にアクセスしたいときに使います。実務での使用頻度は高くありませんが、隣接する要素と比較したい場合などに役立ちます。
const scores = [70, 85, 60, 90];
scores.forEach((score, index, array) => {
if (index > 0) {
const diff = score - array[index - 1];
console.log(`前の要素との差: ${diff}`);
}
});
多くの場合、外側のスコープにある配列変数をそのまま参照すれば十分なため、第3引数を明示的に使う場面は限られます。「配列そのものをコールバックの内側だけで完結させたい」場合にだけ使うと覚えておけば十分です。
03 VS FOR LOOP for文との違い:breakできない理由 forEachの最大の制約を正しく理解する
forEachを使ううえで、最も重要な注意点が「break・continueが使えない」という制約です。
const numbers = [1, 2, 3, 4, 5];
// これはエラーになる(forEach内でbreakは使えない)
numbers.forEach((num) => {
if (num === 3) {
break; // SyntaxError: Illegal break statement
}
console.log(num);
});
forEachのコールバック内でreturnを書いても、forEach全体の処理は止まりません。そのイテレーション(1回分の処理)をスキップして次の要素に進むだけで、for文でいうcontinueに近い動きになります。「returnを書けば途中で抜けられる」という誤解は非常によくある間違いです。
3-1. なぜforEachはbreakできないのか
forEachは内部的に、配列の要素数だけコールバック関数を呼び出す仕組みになっており、途中で処理を打ち切るための仕組みが設計上用意されていません。for文であれば、ループの制御構造そのものにbreakという「抜け道」が組み込まれていますが、forEachは「全要素に対して処理を実行する」ことを前提にしたメソッドだからです。
3-2. 途中で処理を止めたいときの代替手段
もし配列の途中で処理を止めたい場合は、forEachではなく以下のいずれかを検討します。
| 方法 | 特徴 |
|---|---|
| for文(または for...of) | break・continueがそのまま使える。最も直接的な解決策 |
| Array.prototype.some() | 条件がtrueを返した時点でループを打ち切れる(本来は真偽判定用のメソッドだが、早期終了の目的で応用されることがある) |
| Array.prototype.every() | 条件がfalseを返した時点でループを打ち切れる(同上) |
| try-catchで例外を投げる | 意図的に例外を発生させてループを抜ける方法。可読性が下がるためあまり推奨されない |
const numbers = [1, 2, 3, 4, 5];
// for...ofならbreakが使える
for (const num of numbers) {
if (num === 3) break;
console.log(num);
}
// someを使った早期終了の例
numbers.some((num) => {
if (num === 3) return true; // ここでループが止まる
console.log(num);
return false;
});
「途中で処理を止める可能性がある」と分かっている場合は、最初からforEachではなくfor...ofを選んでおくと、後から書き直す手間がありません。「配列を最後まで必ず全部処理する」ことが確定しているときだけforEachを使う、という判断基準を持っておくと迷いません。
04 VS MAP/FILTER map()・filter()との違いと使い分け 似ているようで役割が異なる配列メソッド群
forEachとしばしば混同されるのがmap()とfilter()です。見た目の書き方は似ていますが、戻り値の扱いが根本的に異なります。
| メソッド | 戻り値 | 主な用途 |
|---|---|---|
| forEach() | undefined(戻り値なし) | 各要素に対する処理の実行(副作用が目的) |
| map() | 新しい配列(変換後の値を集めたもの) | 各要素を変換した結果がほしいとき |
| filter() | 新しい配列(条件を満たす要素だけ) | 条件に合う要素だけを抽出したいとき |
const numbers = [1, 2, 3, 4, 5];
// forEach: 戻り値はundefined。ただ処理を実行するだけ
const result1 = numbers.forEach((n) => n * 2);
console.log(result1); // undefined
// map: 変換後の新しい配列が返る
const doubled = numbers.map((n) => n * 2);
console.log(doubled); // [2, 4, 6, 8, 10]
// filter: 条件を満たす要素だけの新しい配列が返る
const evens = numbers.filter((n) => n % 2 === 0);
console.log(evens); // [2, 4]
array.forEach(...)の結果を変数に代入して使おうとするコードをたまに見かけますが、forEachは必ずundefinedを返すため、この使い方は意図通りに動きません。「変換した新しい配列がほしい」場合は必ずmap()を使ってください。
📚 用語解説
副作用(side effect):関数が本来の戻り値以外に、外部の状態(画面表示、変数の書き換え、データベースへの保存など)に影響を与えること。forEachは新しい配列を返さない代わりに、こうした副作用を目的とした処理に向いています。
4-1. reduce()という「集約」のための第4のメソッド
forEach・map・filterと並んでよく使われるのがreduce()です。reduceは配列の全要素を1つの値(合計値や集計オブジェクトなど)に集約したいときに使います。
const prices = [1000, 2000, 1500];
// reduce: 配列を1つの値に集約する
const total = prices.reduce((sum, price) => sum + price, 0);
console.log(total); // 4500
| メソッド | 目的 | 戻り値のイメージ |
|---|---|---|
| forEach | 各要素に処理を実行する(副作用) | なし(undefined) |
| map | 各要素を変換する | 同じ長さの新しい配列 |
| filter | 条件に合う要素を抽出する | 条件を満たす要素だけの配列 |
| reduce | 全要素を1つの値に集約する | 合計値・オブジェクト等、任意の単一の値 |
この4つのメソッドの役割を整理しておくと、「配列に対して何をしたいか」に応じて迷わず適切なメソッドを選べるようになります。forEachは、この中で唯一「新しい値を作らず、ただ実行するだけ」という立ち位置にあることを覚えておいてください。
実務のコードレビューでは、「本来はmapやreduceで書けるはずの処理が、forEachと外側の変数の書き換えで無理やり実現されている」というケースがよく見つかります。可読性の観点からは、目的に合ったメソッドを選ぶことが望ましいとされていますが、チームの慣習やコードの一貫性を優先して、あえてforEachに統一しているプロジェクトも存在します。どちらが正解というより、チーム内でのルールを明確にしておくことが最も重要です。
05 ASYNC PITFALL 非同期処理(async/await)との組み合わせの罠 実務で最も事故が起きやすいforEachの落とし穴
forEachの落とし穴の中でも、特に実務でハマりやすいのがasync/awaitと組み合わせたときの挙動です。
5-1. forEachはコールバックの完了を待たない
forEachのコールバック関数にasync関数を渡しても、forEach自体は各コールバックの処理完了(Promiseの解決)を待たずに、次々と次の要素へ進んでしまいます。
async function fetchData(id) {
// 何か非同期の処理(API呼び出し等)を想定
return new Promise((resolve) => setTimeout(() => resolve(id), 100));
}
const ids = [1, 2, 3];
// 意図:idを1つずつ順番に取得したい
ids.forEach(async (id) => {
const data = await fetchData(id);
console.log(data);
});
console.log('全部の処理が終わったはず');
// 実際の出力順:
// 全部の処理が終わったはず ← 先に実行されてしまう
// 1
// 2
// 3
forEachは、渡したコールバックがPromiseを返す(async関数である)かどうかを気にせず、次のイテレーションへすぐに進みます。そのため「全ての非同期処理が終わってから次の処理をしたい」という意図がある場合、forEachでは実現できません。
5-2. 正しい書き方:for...ofかPromise.allを使う
非同期処理を順番に、あるいは並行に待ちたい場合は、forEachではなく以下のいずれかを使います。
| 方法 | 特徴 |
|---|---|
| for...of + await | 要素を1つずつ順番に処理し、それぞれの完了を待つ(直列処理) |
| Promise.all(array.map(...)) | すべての非同期処理を同時に開始し、全部の完了を待つ(並行処理) |
// 順番に処理を待ちたい場合(直列)
for (const id of ids) {
const data = await fetchData(id);
console.log(data);
}
// 全部同時に開始して、まとめて待ちたい場合(並行)
const results = await Promise.all(ids.map((id) => fetchData(id)));
console.log(results);
「配列の各要素に対して非同期処理を行いたい」と分かった時点で、forEachは選択肢から外し、for...ofかPromise.all(map(...))のどちらかを検討するのが実務の定石です。
非同期処理が必要
API呼び出し等
Yes→for...of
No→Promise.all
候補から除外
完了を待てない
ため
処理が完了
バグを未然に
防止
06 THIS BINDING thisの扱いと第2引数 あまり知られていないforEachのオプション引数
forEachには、コールバック関数に加えて第2引数を渡せることはあまり知られていません。この第2引数は、コールバック関数内でthisとして扱うオブジェクトを指定するためのものです。
const config = { multiplier: 10 };
const numbers = [1, 2, 3];
numbers.forEach(function (num) {
// thisにconfigが束縛される(通常の関数式の場合のみ)
console.log(num * this.multiplier);
}, config);
// 出力: 10, 20, 30
📚 用語解説
this:JavaScriptにおいて、現在実行中の関数がどのオブジェクトに属しているかを参照するキーワード。通常の関数式ではforEachの第2引数で指定したオブジェクトがthisになりますが、アロー関数では外側のスコープのthisがそのまま使われ、第2引数は無視されます。
アロー関数はthisを独自に持たず、常に外側のスコープのthisを引き継ぐ仕様のため、forEachの第2引数を指定しても効果がありません。この第2引数を使いたい場合は、通常の関数式(function構文)を使う必要があります。
実務では、アロー関数が主流になった現在、この第2引数が使われる場面はかなり少なくなっています。ただし、古いコードや他のエンジニアが書いたコードを読む際に遭遇することがあるため、存在だけは知っておくと役立ちます。
07 COMMON MISTAKES 実務でよくある間違いパターン ここまでの内容を「事故のパターン集」として総整理
| 間違いパターン | 症状 | 対策 |
|---|---|---|
| forEach内でbreak/continueを使おうとする | SyntaxErrorになる | for...ofか.some()/.every()を使う |
| forEachの戻り値を使おうとする | 常にundefinedになる | 変換結果が欲しい場合はmap()を使う |
| forEach + async関数で順番を待とうとする | 意図した順序で処理が完了しない | for...of + awaitかPromise.allを使う |
| アロー関数で第2引数のthisを使おうとする | thisが期待通りに束縛されない | 通常の関数式(function)を使う |
| 疎な配列(値が飛び飛びの配列)でforEachを使う | 未定義の添字がスキップされる | 意図した挙動か事前に確認する |
最後の「疎な配列」について補足します。JavaScriptでは以下のように、値が設定されていない添字(穴)を持つ配列を作ることができます。
const sparse = [1, , 3]; // 添字1に値が設定されていない「疎な配列」
sparse.forEach((value) => {
console.log(value);
});
// 出力: 1, 3(添字1の穴はスキップされ、2回しか呼ばれない)
forEachは、この「穴」の部分に対してはコールバックを一切呼び出しません。配列の長さ(length)は3のままなのに、実際にforEachが処理するのは2要素だけ、という直感に反する挙動になるため、疎な配列を扱う可能性がある場合は注意が必要です。
7-1. レビューで確認すべきチェックポイント
社内でJavaScriptのコードレビュールールを作る場合、forEachに関しては以下の観点を確認項目に加えておくと、事故の再発防止に役立ちます。
08 AI CODING 【独自】JSコードレビューでのAIコーディング活用 forEachの落とし穴こそAIレビューが効果を発揮する領域
ここまで紹介してきたforEachの落とし穴——特に「非同期処理を待たない」「breakできない」という挙動は、実はClaude CodeのようなAIコーディングエージェントによるレビューで機械的に検出しやすいパターンです。
📚 用語解説
Claude Code:Anthropicが提供するAIコーディングエージェント。既存のJavaScriptコードを渡して「forEach内でasync/awaitを使っている箇所がないかレビューして」と頼むだけで、経験のあるエンジニアでも見落としがちなパターンを機械的に洗い出してくれます。
弊社(株式会社GENAI)では、社内向けの簡易ツールやスクリプトの実装・レビューにClaude Codeを活用しています。forEachと非同期処理の組み合わせのような「動くけれど意図通りではない」バグは、人間のレビューだけでは見落とされがちな一方、AIによる機械的なパターンチェックとは相性が良い領域です。
8-1. 非エンジニアがコード品質に関わる意味
「JavaScriptは書かないから関係ない」という経営者・管理職の方も多いと思います。しかし、社内ツールや自社サービスの品質は、開発を依頼する立場であっても無関係ではいられないテーマです。「非同期処理の順序がおかしい」というバグは、外部から見ると原因が分かりにくく、調査に想定以上の工数がかかることもあります。
洗い出す
社内ツール等
レビュー依頼
forEach×非同期の
パターンを重点確認
エンジニアが確認
修正案の妥当性を
検証
ルール化
再発防止の
仕組み化
もちろん、AIレビューが万能というわけではありません。最終的にどのような処理フローが業務要件に合っているかという判断は人間の役割であり、AIはあくまで「書かれたコードが意図通りに動くか」を機械的に検証するアシスタントという位置づけです。弊社では開発以外の営業・広告・経理・秘書業務までClaude Codeを組み込んでおり、月額約30,000円(Max 20xプラン)の投資で、こうした地味だが重要な品質チェックまで含めて業務を分担できている実感があります。
8-2. 「動いているから大丈夫」を疑う文化を作る
forEachと非同期処理の組み合わせのように、「エラーは出ないが、意図通りではない」バグは、テスト環境や少量のデータでは気づかれず、本番の大量データで初めて問題が表面化することが少なくありません。こうしたバグを未然に防ぐには、「動いているように見えるコードも、念のためレビューする」という文化を組織に根付かせることが重要です。
Claude Codeのようなツールは、こうした地道なチェックを人手をかけずに継続できる点で、非エンジニアの経営者にとっても投資対効果の高い選択肢になり得ます。
コードの品質担保も、Claude Codeの業務活用も、AI鬼管理が伴走します
「社内ツールの品質を見直したい」「開発以外の業務にもAIを活かしたい」という経営者・管理職の方に向けて、Claude Codeの導入設計をサポートしています。
NEXT STEP
この記事の内容を、あなたのビジネスで
実践してみませんか?
AI活用を自社で回せるようになりたい方へ
AI鬼管理
Claude Code・Cowork導入支援から業務設計・社内浸透まで実践ベースで伴走。「自社で回せる組織」を90日で作る経営者向けトレーニング。
よくある質問
Q. forEachの途中でループを止めることはできますか?
A. forEach自体にはbreak/continueに相当する仕組みがないため、途中で止めることはできません。途中終了が必要な場合は、for...ofや.some()/.every()を使う設計に変更してください。
Q. forEach内でreturnを書くとループ全体が終わりますか?
A. 終わりません。returnはそのイテレーション(1回分の処理)をスキップして次の要素に進むだけで、for文のcontinueに近い動きになります。
Q. forEachとmapはどちらを使えばいいですか?
A. 変換した新しい配列が必要ならmap()、単に各要素に対して処理を実行したいだけ(新しい配列が不要)ならforEachを使います。forEachの戻り値は常にundefinedです。
Q. forEach内でasync/awaitを使うと何が問題になりますか?
A. forEachは各コールバックの完了(Promiseの解決)を待たずに次の要素へ進んでしまうため、非同期処理を順番に待ちたい場合には向いていません。for...of + awaitかPromise.allを使ってください。
Q. forEachはNodeListやMap、Setに対しても使えますか?
A. NodeList(DOM要素のリスト)にもforEachメソッドが用意されています。Map・SetもforEachを持っていますが、コールバックの引数の順序が配列とは異なる場合があるため、それぞれのドキュメントで確認することをお勧めします。
Q. Claude Codeはこうした非同期処理のバグもちゃんと指摘してくれますか?
A. はい。「forEach内で非同期処理の待ち漏れがないかレビューして」といった指示で、経験者でないと気づきにくいパターンを機械的に洗い出すことができます。
Claude Codeで業務自動化を90日で叩き込む
経営者向けの伴走型パーソナルトレーニング
Claude Code を業務に落とし込む
専門研修コース一覧
受講者本人の業務を題材に、「使いこなせる」状態になるまで伴走する研修プログラム。1対1特化型・ハンズオン・法人講座の3コースを展開中。業務特化・実装まで踏み込むタイプのClaude Code研修です。
研修コース一覧を見る →AI鬼管理へのお問い合わせ
この記事を読んで気になった方へ。
AI鬼管理の専門スタッフが、御社に最適な
業務自動化プランを無料でご提案します。




