作成日:2025/5/27,最終更新日:2025/5/27

JavaScript / TypeScriptの繰り返し処理について

繰り返し処理に関する解説 : 応用編

この記事では、繰り返し処理とは何かについて詳しく解説します。


13. ループのネストとその落とし穴

解説: 実務や複雑な処理になると、ループの中にさらにループを書くことがあります。これを「ネスト(入れ子)ループ」と呼びます。
ただし、ネストの深さや書き方によっては、パフォーマンスや可読性の問題を引き起こすこともあるため注意が必要です。




● ネストループの基本形

まずは2重ループのシンプルな例を見てみましょう!

// 例:九九表を出力
for (let i = 1; i <= 9; i++) {
  for (let j = 1; j <= 9; j++) {
    console.log(`${i} × ${j} = ${i * j}`);
  }
}

こうした表や組み合わせ処理にはネストループがよく使われます。


● 落とし穴①:ループが深くなりすぎる

ネストが3重・4重...と深くなっていくと、コードが読みにくくなるだけでなく、処理時間が爆発的に増える危険もあります。

// 3重ネスト(避けたいパターン)
for (let i = 0; i < A.length; i++) {
  for (let j = 0; j < B.length; j++) {
    for (let k = 0; k < C.length; k++) {
      // 何かの組み合わせ処理...
    }
  }
}

特に配列サイズが大きい場合、処理回数が「全ての長さの掛け算」になるため注意が必要です(例:10×10×10=1,000回)。


● 落とし穴②:break / continue の誤用

ネストループ内で breakcontinue を使うと、「どのループに対するものか?」が分かりにくくなります

// 一見 break が外側に見えるが、実は内側だけ抜ける
for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (j === 1) break;
    console.log(i, j);
  }
}

こうしたときは、ラベル付き break を使うことで、外側のループを明示的に抜けることもできます(詳細は第15章で紹介)。


● 解決策:ネストを減らすテクニック

  • ✅ 関数に切り出して責務を分離する
  • ✅ map / flatMap / filter など配列メソッドを活用する
  • ✅ 条件を早めに return や continue で分岐して、処理を絞る

下のように 早期 return + map で書くことで、ネストを減らし読みやすくできます。

// ネストを関数化して整理
function processPairs(arr1, arr2) {
  arr1.forEach(a => {
    arr2.forEach(b => {
      if (a + b > 10) return; // 条件でスキップ(※これは inner forEach をスキップする return)
      console.log(a, b);
    });
  });
}



💡 まとめ:ネストループのコツ!

  • 2重まではOK。それ以上は要注意
  • break / continue の範囲に気をつける
  • 関数化・map / filter の活用で分かりやすく

次は「ループの書き換えチャレンジ」で、実際にネストや構文の変換に挑戦してみましょう!


14. 書き換えチャレンジ:for文 → map / forEach に変換してみよう!

解説: ここまでの章で、for / forEach / map それぞれの特徴や向いている場面を学んできました。
この章では、実際に書き換えながら「どれがベストか?」を体感していきましょう。




● お題①:for文 → forEach に書き換え

以下の for文を、forEachを使って書き換えてみましょう。

// 元のコード
const users = ["太郎", "花子", "次郎"];
for (let i = 0; i < users.length; i++) {
  console.log(users[i] + " さん");    // 結果 : 太郎さん, 花子さん, 次郎さん
}

▼ forEach で書き換えると…

// 書き換え例
users.forEach(user => {
  console.log(user + " さん");    // 結果 : 太郎さん, 花子さん, 次郎さん
});

✅ 処理の目的が「表示すること」なので、副作用ベースの forEach が最適です。


● お題②:for文 → map に書き換え

以下のコードを map を使って書き換えてみましょう。

// 元のコード
const numbers = [1, 2, 3];
const doubled = [];

for (let i = 0; i < numbers.length; i++) {
  doubled.push(numbers[i] * 2);
}
console.log(doubled);    // 結果 : [2, 4, 6]

▼ map で書き換えると…

// 書き換え例
const doubled = numbers.map(num => num * 2);
console.log(doubled);    // 結果 : [2, 4, 6]

✅ 「変換して結果を使う」処理なので、map の目的にぴったりです。


● NG例:「何も返さない」処理に map を使ってしまう

// ❌ よくある間違い(返り値を使っていない map)
numbers.map(num => {
  console.log(num);
});
// mapは新しい配列を返すが、ここでは使われていない → 意味がない

✅ 「返り値が不要」な処理には map は不向き。forEach を使うべきです。




💡 まとめ:書き換えの判断ポイント

  • 処理の目的が「表示や実行(副作用)」なら forEach
  • 処理の目的が「変換して配列として結果を得たい」なら map

「何のために使うのか?」が書き方選びのヒントになる
書き換えを通して、コードの意図や適切な構文選びが自然と身についていきます。

次はいよいよ「ラベル付き文ってなに?」という豆知識編に入っていきます!


15. [参考知識] ラベル付き文ってなに?

解説: JavaScript にはあまり使われることのない構文の1つに、ラベル付き文(labeled statement)があります。
特にネストされたループを「まとめて脱出」したいときに登場します。




● 基本の書き方

// ラベル付きループの構文
outerLoop: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) break outerLoop;  // 「○○○:」がラベル、「break ○○○」でそのまとまり(ループ)を終了できる
    console.log(i, j);
  }
}

✅ この例では、i=1, j=1 の時点で外側のループごと breakされ、ループ処理がすべて終了します。


● 普通の break との違い

// 普通の break だと内側だけ抜ける
for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    if (j === 1) break;
    console.log(i, j);
  }
}

✅ この場合は内側のループだけが止まります。
外側はそのまま i の値を進めてループ継続。


● 注意点:使いすぎ注意!

ラベル付き break は便利ですが、使いすぎるとコードが複雑になりやすいです。
どうしても必要な場面だけに限定し、なるべく関数分けや早期 returnで代替できるならその方が可読性は高くなります。




💡 まとめ:ラベル付き文とは?

  • 多重ループから一気に抜けたいときに使える
  • ラベル名:でループに名前をつけ、break ラベル名で脱出

基本的には「使わずに済む」書き方を選ぶのが望ましい!
例えば、関数の分離・早期 return・フラグ変数などが代替手段になります!

以上、あまり使わないけれど知っておくと便利な「ラベル付き文」でした。
次はいよいよ最終章!「読みやすく、バグりにくいループとは?」を一緒に考えていきましょう!


16. まとめとTips:読みやすく、バグりにくいループとは?

解説: ここまで、ループ処理のさまざまな書き方や応用、注意点を学んできました。
最終章では「じゃあ結局、どう書けばいいの?」という疑問に答えるべく、実務でも通用するループの書き方のコツを紹介します。




● 基本ルール:迷ったら「意図が伝わる書き方」を

ループにはいくつもの選択肢がありますが、目的が明確に伝わる書き方を選ぶことが最優先です。

  • ✅ 新しく別の配列への変換が目的 → map
  • ✅ 条件抽出 → filter
  • ✅ 処理の実行(例:表示・ログ出力など)→ forEach
  • ✅ インデックスが必要/柔軟な制御 → for

同じことができても、「伝わりやすさ」が全然違う。読み手への思いやりが大事です。


● やってしまいがちなNG例

  • map を使っても、返り値を使っていない(forEachが正解)
  • for...in で配列を回している
  • break / continue の影響範囲が不明瞭

これらは一見正しく動くため見逃されやすく、気づかぬうちにバグの温床になってしまうことも。


● ループ処理を洗練させるTips

  • 💡 配列操作は map / filter / reduce で「処理の目的」を明確に
  • 💡 ネストが深くなる場合は関数に切り出す
  • 💡 条件分岐は「早期 return」や「continue」でシンプルに
  • 💡 コメントで「なぜこの書き方か」を軽く補足するのも親切



🎯 まとめ:ループとは「目的を伝える手段」

ループは単なる「繰り返し」ではなく、目的を伝える手段です。
「何をしたいのか」「どう処理したいのか」が明確になるような書き方を意識すれば、読みやすく・バグりにくく・保守しやすいコードに近づいていけます。
どんなに短いループでも、読みやすさを意識したコードはチームや未来の自分を助けてくれます。
ぜひこの知識を、日々の開発や学習に役立ててください!


長編おつかれさまでした!これであなたもループマスターです🙌
もし実務や学習で「どれを使えばいいんだっけ?」と迷ったときは、このガイドを振り返ってみてください。