JavaScriptのループで無限ループが起きる原因と対策を初心者向けに徹底解説!
生徒
「JavaScriptでループを使っていたら、ずっと止まらなくなってしまいました…。パソコンが固まったみたいで怖いです…」
先生
「それは『無限ループ』と呼ばれる現象ですね。ループが終わらない原因と、それを防ぐ方法を一緒に学んでみましょう。」
生徒
「どうしてそんなことが起きるんですか?初心者でも避けられますか?」
先生
「もちろん避けられます!一つ一つ丁寧に見ていきましょう。」
1. 無限ループとは?
JavaScript(ジャバスクリプト)でプログラムを書くとき、同じ処理をくり返す「ループ(繰り返し)」はとても便利です。
しかし、ある条件がずっと満たされないままだと、ループが終わらなくなってしまいます。これを無限ループと呼びます。
無限ループが起きると、ブラウザがフリーズしたり、パソコンの動きが止まってしまったりすることがあります。
2. よく使われるループの書き方
JavaScriptでよく使われるループの1つがwhile文です。
whileとは、「〇〇の間はくり返す」という意味です。
例えば、次のような書き方をします。
let count = 0;
while (count < 5) {
console.log("くり返し中");
count++;
}
くり返し中
くり返し中
くり返し中
くり返し中
くり返し中
この場合、countが0から始まって、1ずつ増えていき、5になるまでループします。
3. 無限ループが起きる例と原因
無限ループが起きてしまうのは、たとえば次のようなコードです。
let number = 1;
while (number < 5) {
console.log("ループ中");
// number++; を書き忘れている!
}
ループ中
ループ中
ループ中
(ずっと続く…)
この例では、numberの値が増えないため、number < 5の条件がいつまでも変わらず、ループが止まりません。
原因は「ループ内で条件が変化しないこと」です。
4. 対策1:変数の更新を忘れない
無限ループを防ぐためには、ループの中で使っている変数の値が、ちゃんと変わるように書くことが大切です。
let number = 1;
while (number < 5) {
console.log("ループ中");
number++; // ここで値を変えることで止まる
}
ループ中
ループ中
ループ中
ループ中
このように、number++(1ずつ増やす)を入れることで、numberが最終的に5になり、ループが止まります。
5. 対策2:ループの条件に気をつける
条件文が間違っていると、無限ループが起こることもあります。
たとえば、「数字が5以上のときに止めたい」のに、number < 5と書いてしまうと、条件が逆になって止まりません。
let number = 10;
while (number < 5) {
console.log("止まりません!");
number++;
}
この例ではnumberが10なので、そもそも条件に入らず、実行されないように見えますが、逆に条件を正しく書いていないと、いつまで経っても終わらないことになります。
6. 対策3:for文ならミスが減る
同じような繰り返しなら、for文を使うと、ミスを減らしやすくなります。
for文では、「スタートの値」「終わりの条件」「1回ごとにどうするか」をすべて一行で書けるからです。
for (let i = 0; i < 5; i++) {
console.log(i + " 回目のくり返し");
}
0 回目のくり返し
1 回目のくり返し
2 回目のくり返し
3 回目のくり返し
4 回目のくり返し
for文はループの中で変数が自動的に変わるため、更新忘れによる無限ループが起きにくいのです。
7. 対策4:ループが止まる条件を先に考える
ループを書くときは、「いつ終わるのか」を最初に考えるようにしましょう。
- 条件を満たさなくなったら止める
- カウンター(数える変数)を使って一定回数で終わらせる
例:5回だけメッセージを表示したい場合
let count = 0;
while (count < 5) {
console.log("表示中:" + count);
count++;
}
8. 対策5:条件が複雑なときは関数に分ける
複雑な条件をループに直接書くと、何が原因で止まらないのかがわかりにくくなります。
そういうときは、条件のチェックを関数にまとめるとわかりやすくなります。
function isContinue(num) {
return num < 10;
}
let number = 0;
while (isContinue(number)) {
console.log("現在の数:" + number);
number++;
}
関数を使うと、「なぜループが止まらないのか」がはっきりしやすくなります。
9. 忘れやすいチェックポイント
- ループの中で変数がちゃんと変わっているか
- ループの条件が正しいか(終わる条件になっているか)
- 間違ってループの中に「無限に実行する処理」がないか
- 動作確認は最初は小さい値で試す(例:5回だけループさせてみる)
まとめ
今回の記事では、JavaScriptプログラミングにおいて誰もが一度は経験する「無限ループ」の原因と、それを確実に回避するための具体的な対策について解説しました。無限ループは単なるバグに留まらず、ユーザーのブラウザをフリーズさせたり、システムのリソースを食いつぶしたりする大きなリスクを秘めています。特にプログラミング初心者の方は、文法を覚えることと同じくらい「どうすれば安全にループを終わらせられるか」という出口戦略を意識することが重要です。
無限ループを未然に防ぐための3つの鉄則
プログラムを動かす前に、以下の3点を自問自答する習慣をつけましょう。これだけで、予期せぬフリーズの大部分は防ぐことができます。
- 変数の更新式は書いたか: while文などを使用する際、ループ内で判定に使っている変数が必ず「終了条件」に向かって変化しているかを確認します。
- 条件式が論理的に正しいか: 「i < 10」と書くべきところを「i > -1」のように書いてしまうと、iが増え続ける限り条件が真のままになり、無限に続いてしまいます。
- for文を優先的に使っているか: 初期化、条件、更新が一箇所にまとまっているfor文は、書き忘れを防ぐ構造上のメリットがあります。
実践的なコード例:安全なループの設計
ループの安全性を高めるために、TypeScriptなどを用いた型安全な実装や、カウンタ変数の明示的な管理を意識してみましょう。例えば、配列の要素を処理する場合、以下のように適切なメソッドを選択することが推奨されます。
// 悪い例:条件が不適切で無限ループになる可能性がある
let n = 0;
// nが偶数の間だけ実行したいつもりが、更新を忘れると大変なことに
/*
while (n % 2 === 0) {
console.log("ループ中...");
// nの更新がない!
}
*/
// 良い例:for文で範囲を限定する
const limit = 10;
for (let i = 0; i < limit; i++) {
if (i % 2 === 0) {
console.log(i + " は偶数です。");
}
}
さらに、より高度な開発現場では、意図しないループを防ぐために「最大実行回数」を設けるガード処理を入れることもあります。これは安全装置のような役割を果たします。
// TypeScriptでの安全なループ実装例
let count: number = 0;
const MAX_ITERATIONS: number = 1000; // 安全のための上限設定
while (true) {
console.log("処理を実行中:" + count);
count++;
// 特定の条件で抜ける
if (count >= 5) {
console.log("目標回数に達したので終了します。");
break;
}
// 万が一のための無限ループ防止ガード
if (count > MAX_ITERATIONS) {
console.error("想定外のループ回数を検知しました。");
break;
}
}
まとめとしての振り返り
JavaScriptの制御構文は非常に強力ですが、正しく制御できなければ諸刃の剣となります。while文やfor文を使う際は、常に「終了条件」を最優先に考えましょう。コードを書いた後に「このループはいつ終わるのか?」と一歩立ち止まって確認するだけで、エンジニアとしての信頼性は格段に向上します。デバッグ時にブラウザが動かなくなったときは、まずループの条件式と変数の更新処理を疑ってみてください。
生徒
「先生、ありがとうございました!無限ループって、ちょっとした書き忘れや勘違いで簡単に起きちゃうんですね。僕もさっき、変数を増やすのを忘れてブラウザを再起動する羽目になりました…。」
先生
「それは良い経験をしましたね。プログラミングにおいて『失敗』は最高の教科書です。ブラウザが固まったら、まずは落ち着いてタブを閉じるか、タスクマネージャーで終了させれば大丈夫ですよ。ところで、無限ループを防ぐ一番簡単な方法は何だったか覚えていますか?」
生徒
「はい!まずはfor文を使うことですね。あらかじめ回数が決まっているなら、初期化も条件も更新も全部1行で書けるから、ミスが減るって学びました。」
先生
「その通りです。では、どうしてもwhile文を使わなきゃいけない場面ではどうしますか?」
生徒
「ループの中で、判定に使っている変数がちゃんと変化しているか確認します。あと、さっきのサンプルコードにあったみたいに、万が一のための『最大回数』を決めておくのも、安全装置みたいでかっこいいなと思いました!」
先生
「素晴らしいですね。その『安全装置』という考え方は、実務でも非常に重要視されます。ユーザーに迷惑をかけないコードを書くのがプロの仕事ですからね。他にも、条件を関数に分ける方法も紹介しましたが、どう感じましたか?」
生徒
「コードがスッキリして、何のためにループしているのか分かりやすくなりました。複雑な条件のときは、頭の中だけで考えずに、ちゃんと名前をつけて整理するのが大事なんですね。」
先生
「正解です!可読性が高いコードは、バグを見つけやすく、無限ループの温床にもなりにくいんです。これからも、動くことだけを目標にするのではなく、『安全に止まること』も意識してコーディングを楽しんでくださいね。」
生徒
「ありがとうございます!次は、もう少し複雑な配列のループ処理にも挑戦してみたいです。条件分岐と組み合わせて、もっと便利なプログラムを作れるように頑張ります!」