📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

概要

JavaScriptの反復処理において、while 文 と do...while 文は、繰り返し回数が事前に決まっていない場面で使用するループ構文である。

while 文は前判定型ループであり、ループ本体を実行する前に条件を評価する。
条件が最初から偽の場合、ループ本体は1度も実行されない。
一方、do...while 文は後判定型ループであり、ループ本体を必ず1回実行してから条件を評価する。
最低1回の実行が保証されるため、ユーザー入力の検証やメニュー表示等に適している。

break 文はループを途中で終了させ、continue 文は現在の反復をスキップして次の反復へ進む。
これらはネストしたループにおいてラベルと組み合わせて使用することで、外側のループを直接制御することもできる。

while 系ループで最も注意すべき問題は無限ループである。
ループ変数の更新忘れや、continue 使用時の更新スキップが主な原因となる。
安全カウンタやタイムアウト機構を導入することで、無限ループの発生を予防できる。


while文

while 文は、指定した条件が真である間、ループ本体を繰り返し実行する前判定型のループ構文である。
繰り返し回数が事前に不定な処理に適している。

基本構文

while 文の構文は以下の通りである。

 while (condition) {
    statement
 }


while 文は、ループ本体を実行する前に condition (条件式) を評価する。
条件式が真 (truthy) であればループ本体を実行し、再び条件式を評価する。
条件式が偽 (falsy) になった時点でループを終了し、ループ直後のコードへ処理が移る。

条件が最初から偽の場合、ループ本体は1度も実行されない。

 let n = 0;
 while (n < 3) {
    console.log(n);
    n++;
 }
 // 出力: 0, 1, 2
 
 // 条件が最初から偽の場合
 let x = 10;
 while (x < 5) {
    console.log(x); // 一度も実行されない
 }


ループ変数の管理

while 文を正しく動作させるには、ループ変数を適切に管理する必要がある。
ループ変数の管理は以下の3段階で構成される。

  • 初期化
    ループ変数は while 文の前で初期化する。
  • 条件式
    ループを継続するかどうかを判定する式をループヘッダに記述する。
  • 更新
    ループ本体の最後でループ変数を更新する。更新を忘れると無限ループになる。


 let i = 0;          // (1) 初期化
 while (i < 5) {     // (2) 条件式
    console.log(i);
    i++;             // (3) 更新
 }


ループ変数の更新をループ本体内のどこに記述するかによって、動作が異なることに注意が必要である。
特に、continue 文と組み合わせる場合は、更新がスキップされないよう慎重に設計する必要がある。

実用的なパターン

while 文が特に有効な実用的なパターンを以下に示す。

条件が不定のループ

取得できるデータが尽きるまで繰り返す処理等、終了条件が事前に決まらない場合に while 文が有効である。

以下の例では、ループ変数 data をループの外で初期化し、ループ本体の末尾で次の値を取得する。

 // データがnullになるまで処理を続ける
 let data = getNextData();
 while (data !== null) {
    processData(data);
    data = getNextData();
 }


カウントダウンループ

初期値から0に向かってカウントダウンするループは、while 文で簡潔に記述できる。

 let countdown = 10;
 while (countdown > 0) {
    console.log(countdown);
    countdown--;
 }

 console.log("発射!");


配列要素の消費

配列から要素を順次取り出して処理するパターンでは、配列が空になったことを条件として使用できる。

 const items = [1, 2, 3, 4, 5];
 
 // pop()で末尾から取り出す
 while (items.length > 0) {
    const item = items.pop();
    console.log(item); // 5, 4, 3, 2, 1
 }
 
 // shift()で先頭から取り出す
 const queue = ["a", "b", "c"];
 while (queue.length > 0) {
    const item = queue.shift();
    console.log(item); // "a", "b", "c"
 }


pop() は配列の末尾から要素を取り出し、shift() は先頭から取り出す。
いずれもループ本体の実行ごとに配列の長さが1減少し、最終的に条件が偽になってループが終了する。


do...while文

do...while 文は、ループ本体を最初に1回実行してから条件を評価する後判定型のループ構文である。
条件の真偽に関わらず、ループ本体が必ず1回は実行されることが保証される。

基本構文

do...while 文の構文は以下の通りである。

 do {
    statement
 } while (condition);


while の後の条件式の末尾にはセミコロンが必要である点に注意する。

 let result = "";
 let i = 0;
 
 do {
    i++;
    result += i;
 } while (i < 5);
 
 console.log(result); // "12345"


この例では、i5 になった時点で条件 i < 5 が偽になりループが終了する。

while文との違い

while 文と do...while 文の最大の違いは、条件式を評価するタイミングである。

while文とdo...while文の比較
比較項目 while文 do...while文
判定タイミング ループ前 (前判定) ループ後 (後判定)
最低実行回数 0回 1回
初期条件が偽の場合 1度も実行されない 1回実行される
主な用途 回数が不定のループ 最低1回の実行が必要なループ
末尾セミコロン 不要 必要 (; で終わる)


以下の例で、2つのループの違いを確認できる。

 // while文: 条件が偽のため一度も実行されない
 let i = 10;
 while (i < 5) {
    console.log("while:", i); // 出力なし
 }
 
 // do...while文: 条件が偽でも1回は実行される
 let j = 10;
 do {
    console.log("do...while:", j); // "do...while: 10"
 } while (j < 5);


実用的なパターン

do...while 文が特に有効な実用的なパターンを以下に示す。

入力の検証ループ

ユーザーからの入力を受け取り、その値が有効かどうかを検証するパターンでは、do...while 文が適している。
最初に入力を受け取ってから検証するため、自然なコードフローになる。

 let score;
 do {
    score = parseInt(prompt("0から100のスコアを入力:"));
 } while (isNaN(score) || score < 0 || score > 100);
 
 console.log("有効なスコア:", score);


入力が有効な範囲外の場合、プロンプトを繰り返し表示する。
有効な値が入力されて初めてループを抜ける。

メニュー表示ループ

アプリケーションのメニューを表示して選択を受け付けるパターンでは、do...while 文が自然に使用できる。
メニューは最低1回は必ず表示される必要があるため、後判定型が適している。

 let choice;
 do {
    displayMenu();
    choice = getUserChoice();
    processChoice(choice);
 } while (choice !== "exit");
 
 console.log("終了しました");


リトライ処理

ネットワーク通信等で失敗した場合に一定回数まで再試行するパターンでも、do...while 文が使われる。

 let success = false;
 let retries = 0;
 const maxRetries = 3;
 
 do {
    try {
       const response = await fetch(url);
       if (response.ok) {
          success = true;
          console.log("接続成功");
       }
    } catch (error) {
       retries++;
       console.log(`試行 ${retries} 回目失敗:`, error.message);
    }
 } while (!success && retries < maxRetries);
 
 if (!success) {
    console.log("最大試行回数に達しました");
 }


最初の試行を必ず1回実行し、失敗した場合のみ再試行する。
成功するか最大試行回数に達した時点でループを抜ける。


break文

break 文は、現在のループ (whiledo...whilefor)、または switch 文を即座に終了させる制御構文である。
break 文が実行されると、ループの残りの処理をスキップしてループ直後のコードへ処理が移る。

基本的な使用方法

break 文を使用することで、特定の条件が満たされた時点でループを終了させることができる。

 // 目的の値が見つかったらループを抜ける
 const numbers = [1, 3, 5, 8, 9, 11];
 let found = -1;
 
 let i = 0;
 while (i < numbers.length) {
    if (numbers[i] % 2 === 0) {
       found = numbers[i];
       break; // 最初の偶数が見つかった時点でループを終了
    }
    i++;
 }
 
 console.log("最初の偶数:", found); // 8


break 文はネストしたループの内側にある場合、最も内側のループのみを終了させる。
外側のループは継続される。

 for (let i = 0; i < 3; i++) {
    let j = 0;
    while (j < 3) {
       if (j === 1) break; // 内側のwhileループを終了
       console.log(i, j);
       j++;
    }
    // 外側のforループは継続される
 }
 // 出力: 0 0, 1 0, 2 0


ラベル付きbreak

ネストしたループで外側のループを直接終了させる場合、ラベル付きbreak を使用する。
ラベルはループの直前にコロンを付けて定義する。

 const matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
 ];
 const target = 5;
 let foundRow = -1;
 let foundCol = -1;
 
 outerLoop: for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[i].length; j++) {
       if (matrix[i][j] === target) {
          foundRow = i;
          foundCol = j;
          break outerLoop; // 外側のforループを終了
       }
    }
 }
 
 console.log(`found at [${foundRow}][${foundCol}]`); // found at [1][1]


ラベル付きbreak は、2次元配列の検索や複雑なネスト構造のループからの脱出に使用される。
ただし、ラベルの多用はソースコードの可読性を下げるため、使用は必要最小限に留めることが推奨される。

switchとbreak

break 文は、switch 文の各caseの末尾にも使用する。
switch 文では break を省略すると次のcaseに処理が流れるフォールスルーが発生するため、意図的なフォールスルーでない限り各caseには break を記述する。

switch 文の詳細については、JavaScriptの基礎 - 条件分岐のページを参照すること。

 const day = "Monday";
 switch (day) {
    case "Monday":
       console.log("月曜日");
       break; // break がなければ次の case へフォールスルー
    case "Tuesday":
       console.log("火曜日");
       break;
    default:
       console.log("その他の曜日");
       break;
 }



continue文

continue 文は、現在の反復処理をスキップして次の反復へ進む制御構文である。
break 文がループ全体を終了させるのに対し、continue 文は現在の反復のみをスキップする。

基本的な使い方

continue 文を使用することにより、特定の条件を満たす要素をスキップしながらループを継続できる。

 // 偶数のみを出力する
 let i = 0;
 while (i < 10) {
    i++;
    if (i % 2 !== 0) continue; // 奇数をスキップ
    console.log(i); // 2, 4, 6, 8, 10
 }


forループでのcontinue

for ループで continue を使用する場合、更新式 (カウンタのインクリメント) は continue 後も必ず実行される。
これは while ループとの重要な違いである。

 for (let i = 0; i < 10; i++) {
    if (i === 3) continue; // i++ は continue の後も実行される
    console.log(i); // 3以外の 0, 1, 2, 4, 5, 6, 7, 8, 9 が出力
 }


for ループでは、continue が実行された後、ループヘッダの更新式 (i++) が実行されてから次の条件判定が行われる。
このため、無限ループになる危険性はない。

whileループでのcontinue

while ループで continue を使用する場合は、ループ変数の更新に注意が必要である。
continue の後にループ変数の更新コードがある場合、その更新がスキップされて無限ループになる危険性がある。

 // 危険なパターン: 無限ループになる
 let i = 0;
 while (i < 5) {
    if (i === 3) continue; // i の更新がスキップされる!
    i++;                   // i === 3 のとき、この行は実行されない
 }
 
 // 安全なパターン: 更新をcontinueの前に移動
 let j = 0;
 while (j < 5) {
    j++; // 先に更新してからスキップ判定
    if (j === 3) continue;
    console.log(j); // 1, 2, 4, 5
 }
 
 // もう1つの安全なパターン: continue の前に更新を記述
 let k = 0;
 while (k < 5) {
    if (k === 3) {
       k++; // スキップ前に更新する
       continue;
    }
    console.log(k);
    k++;
 }


while ループで continue を使用する場合は、ループ変数の更新が必ず実行されるよう設計する必要がある。

ラベル付きcontinue

ネストしたループで外側のループの次の反復へジャンプする場合、ラベル付きcontinue を使用する。

 const matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
 ];
 
 // 特定の行をスキップする
 outerLoop: for (let i = 0; i < matrix.length; i++) {
    for (let j = 0; j < matrix[i].length; j++) {
       if (matrix[i][j] === 5) {
          continue outerLoop; // 外側のループの次の反復へジャンプ
       }
       console.log(matrix[i][j]);
    }
 }
 // 出力: 1, 2, 3, 4 (5が含まれる行の残り 6 がスキップされる), 7, 8, 9


ラベル付きcontinue により、内側のループで特定の条件を満たした時点で外側のループの次の反復に進むことができる。


無限ループの回避

無限ループとは、終了条件が満たされることなく永久に繰り返されるループのことである。

while 系ループではループ変数の管理を自分で行う必要があるため、無限ループが発生しやすい。

無限ループの原因

無限ループが発生する主な原因を以下に示す。

  • ループ変数の更新忘れ
    ループ本体でループ変数を更新しないと、条件式が常に真のまま変化しない。
     // 無限ループの例: i が更新されない
     let i = 0;
     while (i < 10) {
        console.log(i);
        // i++ を忘れている
     }
    

  • continueによる更新スキップ
    continue の後にループ変数の更新があると、スキップされて無限ループになる。
     // 無限ループの例: i === 3 のとき i++ がスキップされる
     let i = 0;
     while (i < 5) {
        if (i === 3) continue;
        i++;
     }
    

  • 終了条件が到達不可能
    ループ変数は更新されているが、条件式が偽になる値に到達できない場合も無限ループになる。
     // 無限ループの例: i が減少しているが条件は増加方向
     let i = 10;
     while (i < 100) {
        console.log(i);
        i--; // i は減少しているので条件 i < 100 は常に真
     }
    

  • 外部状態に依存した条件の変化忘れ
    外部関数が返す値や外部変数に依存した条件で、その状態が変化しない場合も無限ループになる。


予防策

無限ループを防ぐための予防策を以下に示す。

安全カウンタの導入

ループに安全カウンタを設けることにより、一定回数以上の反復を強制的に停止できる。

 let iterations = 0;
 const maxIterations = 10000;
 
 while (condition && iterations < maxIterations) {
    iterations++;
    // 処理
 }
 
 if (iterations >= maxIterations) {
    console.warn("最大反復回数に達しました。ループを強制終了します。");
 }


タイムアウト機構の導入

時間ベースの終了条件を設けることにより、処理時間が長くなりすぎることを防ぐ。

 const startTime = Date.now();
 const timeout = 5000; // 5秒
 
 while (condition) {
    if (Date.now() - startTime > timeout) {
       console.warn("タイムアウト: ループを強制終了します。");
       break;
    }
    // 処理
 }


ループ変数の管理を明確にする

ループ変数の初期化、条件式、更新を一目で確認できるよう、ソースコードを整理する。
更新漏れを防ぐために、更新処理はループ本体の先頭か末尾に統一して配置することが推奨される。

 // 推奨: 更新をループ本体の末尾に統一
 let i = 0; // (1) 初期化
 while (i < limit) { // (2) 条件式
    // 処理
    i++; // (3) 更新 (常に最後)
 }


無限ループの検出と対処

実行中に無限ループを検出した場合の対処方法を以下に示す。

  • Webブラウザでの対処
    [Ctrl] + [C]キー または [Ctrl] + [W]キーでスクリプトを停止する。
    Webブラウザのタブを強制終了する。
    デベロッパーツールのSourcesパネルで一時停止ボタンを使用する。

  • Node.jsでの対処
    [Ctrl] + [C]キーでプロセスを停止する。
    別のターミナルから kill コマンドでプロセスを終了する。

  • デバッグ方法
    ループの反復回数をカウントするカウンタ変数を追加する。
    console.log でループ変数の変化を追跡する。
    ブレークポイントを設定してステップ実行で状態を確認する。


 // デバッグ用カウンタを追加した例
 let i = 0;
 let debugCount = 0;
 
 while (someCondition) {
    debugCount++;
    console.log(`反復 ${debugCount}: i = ${i}`);
 
    if (debugCount > 1000) {
       console.error("無限ループの可能性を検出");
       break;
    }
 
    // ...処理
 }



while系ループとfor系ループの使い分け

JavaScriptには複数のループ構文が用意されており、それぞれ適した用途がある。
ループ構文を適切に選択することで、ソースコードの可読性と保守性が向上する。

ループ構文の比較
ループ 初期化 条件判定 更新 最低実行回数 最適な用途
while ループ外 ループ前 ループ内 0回 繰り返し回数が不定なループ
do...while ループ外 ループ後 ループ内 1回 最低1回の実行が必要なループ
for ループ式内 ループ式内 ループ式内 0回 繰り返し回数が決まっているループ
for...of 不要 (自動) 自動 自動 0回 イテラブルの値を順に処理するループ


各ループ構文の選択基準を以下に示す。

ループ構文の選択基準
ループ構文 選択基準
while文 繰り返し回数が事前に不定な場合
特定の条件が変化するまで繰り返す場合
データを順次取得しながら処理する場合
do...while文 ループ本体を最低1回は必ず実行する必要がある場合
ユーザ入力の検証
メニュー表示
リトライ処理
for文 繰り返し回数が事前にわかっている場合
インデックスを使った配列へのアクセスが必要な場合
複数のカウンタ変数を同時に制御する場合
for...of文 配列
文字列
Map、Set等のイテラブルを順に処理する場合
インデックスが不要で値のみを扱う場合


for...of の詳細については、JavaScriptの基礎 - 反復処理(for文)のページを参照すること。


関連情報