概要
ループは、プログラミングにおける最も基本的な制御構文だ。
しかしJavaScriptでは、ループの手段が多すぎる。
for
forEach
map
reduce
for...of
for...in
「なんとなく使ってる」では、バグ・非効率・可読性の劣化を招く。
この記事では、それぞれのループ構文の構文的な違いと使い分けの判断軸を、設計目線で整理していく。
対象環境
ES6以降のJavaScript(Node.js / ブラウザ)
各ループ構文の特徴と選定基準
構文 | 主な用途 | 副作用あり | return値 | 中断可 | イテラブル対応 | 適しているケース |
---|---|---|---|---|---|---|
for |
汎用 | ✅ | ❌ undefined | ✅ break 可 |
✅ | 制御フローが複雑 / 索引アクセスが必要 |
forEach |
配列の処理 | ✅ | ❌ undefined | ❌不可 | ✅ | 単純な副作用処理 |
map |
配列を変換して返す | ❌推奨外 | ✅ 配列 | ❌不可 | ✅ | 配列変換ロジック |
reduce |
配列を単一値に畳み込む | ❌推奨外 | ✅ 任意値 | ❌不可 | ✅ | 集計・合計・構造変換 |
for...of |
任意のイテラブル処理 | ✅ | ❌ undefined | ✅ break 可 |
✅ | 配列 / Set / Map の繰り返し処理 |
for...in |
オブジェクト列挙 | ✅ | ❌ undefined | ✅ break 可 |
❌ | キー列挙のみ。配列には不向き |
それぞれの実例と解説
1. for
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
- ✅ 高い柔軟性
- ❌ 長くなりがち
- ✅ 中断可能 (
break
,continue
)
2. forEach
items.forEach(item => {
console.log(item);
});
- ✅ 簡潔
- ❌
return
,break
できない - ❌ チェーン不可(return値なし)
3. map
const doubled = items.map(x => x * 2);
- ✅ 「変換」に強い(1対1の変換)
- ❌ 副作用は禁止
- ✅ チェーン可能
4. reduce
const total = items.reduce((acc, cur) => acc + cur, 0);
- ✅ 単一値の集約に最適
- ✅ 初期値を使って安全に設計可能
- ❌ 初見では読みにくいことも
5. for...of
for (const item of items) {
console.log(item);
}
- ✅ シンプルで安全
- ✅ break / continue / return 可能
- ✅ 配列 / Set / Map / arguments に対応
6. for...in
for (const key in obj) {
console.log(`${key}: ${obj[key]}`);
}
- ✅ オブジェクトのキー列挙に適している
- ❌ 配列に使うとインデックス順が保証されない
- ❌ プロトタイプ継承の影響を受ける
→ ✅ Object.hasOwn()
との併用が安全:
for (const key in obj) {
if (Object.hasOwn(obj, key)) {
// ...
}
}
ループ選定の設計思考
目的 | 推奨構文 |
---|---|
配列を変換したい | map |
累積して1つの値を導出したい | reduce |
副作用処理(API呼び出しなど) | forEach |
breakしたい |
for , for...of
|
イテラブル全般を処理したい | for...of |
オブジェクトのキーを走査 |
for...in (+ hasOwn) |
よくある誤用
❌ map
を副作用目的で使う
items.map(item => console.log(item)); // ❌ 非推奨
→ ✅ forEach
もしくは for...of
を使うべき
❌ for...in
を配列に使う
for (const i in arr) {
console.log(arr[i]); // ❌ インデックス順を保証しない
}
→ ✅ for
, for...of
が適切
❌ forEach
で早期リターンしようとする
items.forEach(item => {
if (item > 10) return; // ❌ これは次のループをスキップしない
});
→ ✅ for
/ for...of
に置き換える
結語
ループ処理とは、単なる反復ではない。
意図を明示するための制御構造であり、責任の分岐点でもある。
すべてのループ構文には、それが設計された理由がある。
その意図を汲み取り、機能だけでなく意味を持った選定を行うこと。
コードの動作を決めるのは構文だが、
コードの価値を決めるのは設計である。