この記事では、繰り返し処理とは何かについて詳しく解説します。
解説:
実務や複雑な処理になると、ループの中にさらにループを書くことがあります。これを「ネスト(入れ子)ループ」と呼びます。
ただし、ネストの深さや書き方によっては、パフォーマンスや可読性の問題を引き起こすこともあるため注意が必要です。
まずは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 を使うと、「どのループに対するものか?」が分かりにくくなります。
// 一見 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章で紹介)。
下のように 早期 return + map で書くことで、ネストを減らし読みやすくできます。
// ネストを関数化して整理
function processPairs(arr1, arr2) {
arr1.forEach(a => {
arr2.forEach(b => {
if (a + b > 10) return; // 条件でスキップ(※これは inner forEach をスキップする return)
console.log(a, b);
});
});
}次は「ループの書き換えチャレンジ」で、実際にネストや構文の変換に挑戦してみましょう!
解説:
ここまでの章で、for / forEach / map それぞれの特徴や向いている場面を学んできました。
この章では、実際に書き換えながら「どれがベストか?」を体感していきましょう。
以下の for文を、forEachを使って書き換えてみましょう。
// 元のコード
const users = ["太郎", "花子", "次郎"];
for (let i = 0; i < users.length; i++) {
console.log(users[i] + " さん"); // 結果 : 太郎さん, 花子さん, 次郎さん
}▼ forEach で書き換えると…
// 書き換え例
users.forEach(user => {
console.log(user + " さん"); // 結果 : 太郎さん, 花子さん, 次郎さん
});✅ 処理の目的が「表示すること」なので、副作用ベースの forEach が最適です。
以下のコードを 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 の目的にぴったりです。
// ❌ よくある間違い(返り値を使っていない map)
numbers.map(num => {
console.log(num);
});
// mapは新しい配列を返すが、ここでは使われていない → 意味がない✅ 「返り値が不要」な処理には map は不向き。forEach を使うべきです。
forEachmap
「何のために使うのか?」が書き方選びのヒントになる
書き換えを通して、コードの意図や適切な構文選びが自然と身についていきます。
次はいよいよ「ラベル付き文ってなに?」という豆知識編に入っていきます!
解説:
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 だと内側だけ抜ける
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・フラグ変数などが代替手段になります!
以上、あまり使わないけれど知っておくと便利な「ラベル付き文」でした。
次はいよいよ最終章!「読みやすく、バグりにくいループとは?」を一緒に考えていきましょう!
解説:
ここまで、ループ処理のさまざまな書き方や応用、注意点を学んできました。
最終章では「じゃあ結局、どう書けばいいの?」という疑問に答えるべく、実務でも通用するループの書き方のコツを紹介します。
ループにはいくつもの選択肢がありますが、目的が明確に伝わる書き方を選ぶことが最優先です。
mapfilterforEachfor同じことができても、「伝わりやすさ」が全然違う。読み手への思いやりが大事です。
これらは一見正しく動くため見逃されやすく、気づかぬうちにバグの温床になってしまうことも。
ループは単なる「繰り返し」ではなく、目的を伝える手段です。
「何をしたいのか」「どう処理したいのか」が明確になるような書き方を意識すれば、読みやすく・バグりにくく・保守しやすいコードに近づいていけます。
どんなに短いループでも、読みやすさを意識したコードはチームや未来の自分を助けてくれます。
ぜひこの知識を、日々の開発や学習に役立ててください!
長編おつかれさまでした!これであなたもループマスターです🙌
もし実務や学習で「どれを使えばいいんだっけ?」と迷ったときは、このガイドを振り返ってみてください。