MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
JavaScriptの基礎 - 反復処理(while文)のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
JavaScriptの基礎 - 反復処理(while文)
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == JavaScriptの反復処理において、<code>while</code> 文 と <code>do...while</code> 文は、繰り返し回数が事前に決まっていない場面で使用するループ構文である。<br> <br> <code>while</code> 文は前判定型ループであり、ループ本体を実行する前に条件を評価する。<br> 条件が最初から偽の場合、ループ本体は1度も実行されない。<br> 一方、<code>do...while</code> 文は後判定型ループであり、ループ本体を必ず1回実行してから条件を評価する。<br> 最低1回の実行が保証されるため、ユーザー入力の検証やメニュー表示等に適している。<br> <br> <code>break</code> 文はループを途中で終了させ、<code>continue</code> 文は現在の反復をスキップして次の反復へ進む。<br> これらはネストしたループにおいてラベルと組み合わせて使用することで、外側のループを直接制御することもできる。<br> <br> <code>while</code> 系ループで最も注意すべき問題は無限ループである。<br> ループ変数の更新忘れや、<code>continue</code> 使用時の更新スキップが主な原因となる。<br> 安全カウンタやタイムアウト機構を導入することで、無限ループの発生を予防できる。<br> <br><br> == while文 == <code>while</code> 文は、指定した条件が真である間、ループ本体を繰り返し実行する前判定型のループ構文である。<br> 繰り返し回数が事前に不定な処理に適している。<br> <br> ==== 基本構文 ==== <code>while</code> 文の構文は以下の通りである。<br> <br> <syntaxhighlight lang="javascript"> while (condition) { statement } </syntaxhighlight> <br> <code>while</code> 文は、ループ本体を実行する前に <code>condition</code> (条件式) を評価する。<br> 条件式が真 (truthy) であればループ本体を実行し、再び条件式を評価する。<br> 条件式が偽 (falsy) になった時点でループを終了し、ループ直後のコードへ処理が移る。<br> <br> 条件が最初から偽の場合、ループ本体は1度も実行されない。<br> <br> <syntaxhighlight lang="javascript"> let n = 0; while (n < 3) { console.log(n); n++; } // 出力: 0, 1, 2 // 条件が最初から偽の場合 let x = 10; while (x < 5) { console.log(x); // 一度も実行されない } </syntaxhighlight> <br> ==== ループ変数の管理 ==== <code>while</code> 文を正しく動作させるには、ループ変数を適切に管理する必要がある。<br> ループ変数の管理は以下の3段階で構成される。<br> <br> * 初期化 *: ループ変数は <code>while</code> 文の前で初期化する。 * 条件式 *: ループを継続するかどうかを判定する式をループヘッダに記述する。 * 更新 *: ループ本体の最後でループ変数を更新する。更新を忘れると無限ループになる。 <br> <syntaxhighlight lang="javascript"> let i = 0; // (1) 初期化 while (i < 5) { // (2) 条件式 console.log(i); i++; // (3) 更新 } </syntaxhighlight> <br> ループ変数の更新をループ本体内のどこに記述するかによって、動作が異なることに注意が必要である。<br> 特に、<code>continue</code> 文と組み合わせる場合は、更新がスキップされないよう慎重に設計する必要がある。<br> <br> ==== 実用的なパターン ==== <code>while</code> 文が特に有効な実用的なパターンを以下に示す。<br> <br> ===== 条件が不定のループ ===== 取得できるデータが尽きるまで繰り返す処理等、終了条件が事前に決まらない場合に <code>while</code> 文が有効である。<br> <br> 以下の例では、ループ変数 <code>data</code> をループの外で初期化し、ループ本体の末尾で次の値を取得する。<br> <br> <syntaxhighlight lang="javascript"> // データがnullになるまで処理を続ける let data = getNextData(); while (data !== null) { processData(data); data = getNextData(); } </syntaxhighlight> <br> ===== カウントダウンループ ===== 初期値から0に向かってカウントダウンするループは、<code>while</code> 文で簡潔に記述できる。<br> <br> <syntaxhighlight lang="javascript"> let countdown = 10; while (countdown > 0) { console.log(countdown); countdown--; } console.log("発射!"); </syntaxhighlight> <br> ===== 配列要素の消費 ===== 配列から要素を順次取り出して処理するパターンでは、配列が空になったことを条件として使用できる。<br> <br> <syntaxhighlight lang="javascript"> 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" } </syntaxhighlight> <br> <code>pop()</code> は配列の末尾から要素を取り出し、<code>shift()</code> は先頭から取り出す。<br> いずれもループ本体の実行ごとに配列の長さが1減少し、最終的に条件が偽になってループが終了する。<br> <br><br> == do...while文 == <code>do...while</code> 文は、ループ本体を最初に1回実行してから条件を評価する後判定型のループ構文である。<br> <u>条件の真偽に関わらず、ループ本体が必ず1回は実行されることが保証される。</u><br> <br> ==== 基本構文 ==== <code>do...while</code> 文の構文は以下の通りである。<br> <br> <syntaxhighlight lang="javascript"> do { statement } while (condition); </syntaxhighlight> <br> <code>while</code> の後の条件式の末尾にはセミコロンが必要である点に注意する。<br> <br> <syntaxhighlight lang="javascript"> let result = ""; let i = 0; do { i++; result += i; } while (i < 5); console.log(result); // "12345" </syntaxhighlight> <br> この例では、<code>i</code> が <code>5</code> になった時点で条件 <code>i < 5</code> が偽になりループが終了する。<br> <br> ==== while文との違い ==== <code>while</code> 文と <code>do...while</code> 文の最大の違いは、条件式を評価するタイミングである。<br> <br> <center> {| class="wikitable" |+ while文とdo...while文の比較 ! 比較項目 !! while文 !! do...while文 |- | 判定タイミング || ループ前 (前判定) || ループ後 (後判定) |- | 最低実行回数 || 0回 || 1回 |- | 初期条件が偽の場合 || 1度も実行されない || 1回実行される |- | 主な用途 || 回数が不定のループ || 最低1回の実行が必要なループ |- | 末尾セミコロン || 不要 || 必要 (; で終わる) |} </center> <br> 以下の例で、2つのループの違いを確認できる。<br> <br> <syntaxhighlight lang="javascript"> // 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); </syntaxhighlight> <br> ==== 実用的なパターン ==== <code>do...while</code> 文が特に有効な実用的なパターンを以下に示す。<br> <br> ===== 入力の検証ループ ===== ユーザーからの入力を受け取り、その値が有効かどうかを検証するパターンでは、<code>do...while</code> 文が適している。<br> 最初に入力を受け取ってから検証するため、自然なコードフローになる。<br> <br> <syntaxhighlight lang="javascript"> let score; do { score = parseInt(prompt("0から100のスコアを入力:")); } while (isNaN(score) || score < 0 || score > 100); console.log("有効なスコア:", score); </syntaxhighlight> <br> 入力が有効な範囲外の場合、プロンプトを繰り返し表示する。<br> 有効な値が入力されて初めてループを抜ける。<br> <br> ===== メニュー表示ループ ===== アプリケーションのメニューを表示して選択を受け付けるパターンでは、<code>do...while</code> 文が自然に使用できる。<br> メニューは最低1回は必ず表示される必要があるため、後判定型が適している。<br> <br> <syntaxhighlight lang="javascript"> let choice; do { displayMenu(); choice = getUserChoice(); processChoice(choice); } while (choice !== "exit"); console.log("終了しました"); </syntaxhighlight> <br> ===== リトライ処理 ===== ネットワーク通信等で失敗した場合に一定回数まで再試行するパターンでも、<code>do...while</code> 文が使われる。<br> <br> <syntaxhighlight lang="javascript"> 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("最大試行回数に達しました"); } </syntaxhighlight> <br> 最初の試行を必ず1回実行し、失敗した場合のみ再試行する。<br> 成功するか最大試行回数に達した時点でループを抜ける。<br> <br><br> == break文 == <code>break</code> 文は、現在のループ (<code>while</code>、<code>do...while</code>、<code>for</code>)、または <code>switch</code> 文を即座に終了させる制御構文である。<br> <code>break</code> 文が実行されると、ループの残りの処理をスキップしてループ直後のコードへ処理が移る。<br> <br> ==== 基本的な使用方法 ==== <code>break</code> 文を使用することで、特定の条件が満たされた時点でループを終了させることができる。<br> <br> <syntaxhighlight lang="javascript"> // 目的の値が見つかったらループを抜ける 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 </syntaxhighlight> <br> <code>break</code> 文はネストしたループの内側にある場合、最も内側のループのみを終了させる。<br> 外側のループは継続される。<br> <br> <syntaxhighlight lang="javascript"> 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 </syntaxhighlight> <br> ==== ラベル付きbreak ==== ネストしたループで外側のループを直接終了させる場合、<code>ラベル付きbreak</code> を使用する。<br> ラベルはループの直前にコロンを付けて定義する。<br> <br> <syntaxhighlight lang="javascript"> 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] </syntaxhighlight> <br> <code>ラベル付きbreak</code> は、2次元配列の検索や複雑なネスト構造のループからの脱出に使用される。<br> ただし、ラベルの多用はソースコードの可読性を下げるため、使用は必要最小限に留めることが推奨される。<br> <br> ==== switchとbreak ==== <code>break</code> 文は、<code>switch</code> 文の各caseの末尾にも使用する。<br> <code>switch</code> 文では <code>break</code> を省略すると次のcaseに処理が流れるフォールスルーが発生するため、意図的なフォールスルーでない限り各caseには <code>break</code> を記述する。<br> <br> <code>switch</code> 文の詳細については、[[JavaScriptの基礎 - 条件分岐]]のページを参照すること。<br> <br> <syntaxhighlight lang="javascript"> const day = "Monday"; switch (day) { case "Monday": console.log("月曜日"); break; // break がなければ次の case へフォールスルー case "Tuesday": console.log("火曜日"); break; default: console.log("その他の曜日"); break; } </syntaxhighlight> <br><br> == continue文 == <code>continue</code> 文は、現在の反復処理をスキップして次の反復へ進む制御構文である。<br> <code>break</code> 文がループ全体を終了させるのに対し、<code>continue</code> 文は現在の反復のみをスキップする。<br> <br> ==== 基本的な使い方 ==== <code>continue</code> 文を使用することにより、特定の条件を満たす要素をスキップしながらループを継続できる。<br> <br> <syntaxhighlight lang="javascript"> // 偶数のみを出力する let i = 0; while (i < 10) { i++; if (i % 2 !== 0) continue; // 奇数をスキップ console.log(i); // 2, 4, 6, 8, 10 } </syntaxhighlight> <br> ==== forループでのcontinue ==== <code>for</code> ループで <code>continue</code> を使用する場合、更新式 (カウンタのインクリメント) は <code>continue</code> 後も必ず実行される。<br> これは <code>while</code> ループとの重要な違いである。<br> <br> <syntaxhighlight lang="javascript"> 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 が出力 } </syntaxhighlight> <br> <code>for</code> ループでは、<code>continue</code> が実行された後、ループヘッダの更新式 (<u>i++</u>) が実行されてから次の条件判定が行われる。<br> このため、無限ループになる危険性はない。<br> <br> ==== whileループでのcontinue ==== <code>while</code> ループで <code>continue</code> を使用する場合は、ループ変数の更新に注意が必要である。<br> <code>continue</code> の後にループ変数の更新コードがある場合、その更新がスキップされて無限ループになる危険性がある。<br> <br> <syntaxhighlight lang="javascript"> // 危険なパターン: 無限ループになる 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++; } </syntaxhighlight> <br> <code>while</code> ループで <code>continue</code> を使用する場合は、ループ変数の更新が必ず実行されるよう設計する必要がある。<br> <br> ==== ラベル付きcontinue ==== ネストしたループで外側のループの次の反復へジャンプする場合、<code>ラベル付きcontinue</code> を使用する。<br> <br> <syntaxhighlight lang="javascript"> 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 </syntaxhighlight> <br> <code>ラベル付きcontinue</code> により、内側のループで特定の条件を満たした時点で外側のループの次の反復に進むことができる。<br> <br><br> == 無限ループの回避 == 無限ループとは、終了条件が満たされることなく永久に繰り返されるループのことである。<br> <br> <code>while</code> 系ループではループ変数の管理を自分で行う必要があるため、無限ループが発生しやすい。<br> <br> ==== 無限ループの原因 ==== 無限ループが発生する主な原因を以下に示す。<br> <br> * ループ変数の更新忘れ *: ループ本体でループ変数を更新しないと、条件式が常に真のまま変化しない。 *: <syntaxhighlight lang="javascript"> // 無限ループの例: i が更新されない let i = 0; while (i < 10) { console.log(i); // i++ を忘れている } </syntaxhighlight> *: <br> * continueによる更新スキップ *: <code>continue</code> の後にループ変数の更新があると、スキップされて無限ループになる。 *: <syntaxhighlight lang="javascript"> // 無限ループの例: i === 3 のとき i++ がスキップされる let i = 0; while (i < 5) { if (i === 3) continue; i++; } </syntaxhighlight> *: <br> * 終了条件が到達不可能 *: ループ変数は更新されているが、条件式が偽になる値に到達できない場合も無限ループになる。 *: <syntaxhighlight lang="javascript"> // 無限ループの例: i が減少しているが条件は増加方向 let i = 10; while (i < 100) { console.log(i); i--; // i は減少しているので条件 i < 100 は常に真 } </syntaxhighlight> *: <br> * 外部状態に依存した条件の変化忘れ *: 外部関数が返す値や外部変数に依存した条件で、その状態が変化しない場合も無限ループになる。 <br> ==== 予防策 ==== 無限ループを防ぐための予防策を以下に示す。<br> <br> ===== 安全カウンタの導入 ===== ループに安全カウンタを設けることにより、一定回数以上の反復を強制的に停止できる。<br> <br> <syntaxhighlight lang="javascript"> let iterations = 0; const maxIterations = 10000; while (condition && iterations < maxIterations) { iterations++; // 処理 } if (iterations >= maxIterations) { console.warn("最大反復回数に達しました。ループを強制終了します。"); } </syntaxhighlight> <br> ===== タイムアウト機構の導入 ===== 時間ベースの終了条件を設けることにより、処理時間が長くなりすぎることを防ぐ。<br> <br> <syntaxhighlight lang="javascript"> const startTime = Date.now(); const timeout = 5000; // 5秒 while (condition) { if (Date.now() - startTime > timeout) { console.warn("タイムアウト: ループを強制終了します。"); break; } // 処理 } </syntaxhighlight> <br> ===== ループ変数の管理を明確にする ===== ループ変数の初期化、条件式、更新を一目で確認できるよう、ソースコードを整理する。<br> 更新漏れを防ぐために、更新処理はループ本体の先頭か末尾に統一して配置することが推奨される。<br> <br> <syntaxhighlight lang="javascript"> // 推奨: 更新をループ本体の末尾に統一 let i = 0; // (1) 初期化 while (i < limit) { // (2) 条件式 // 処理 i++; // (3) 更新 (常に最後) } </syntaxhighlight> <br> ==== 無限ループの検出と対処 ==== 実行中に無限ループを検出した場合の対処方法を以下に示す。<br> <br> * Webブラウザでの対処 *: [Ctrl] + [C]キー または [Ctrl] + [W]キーでスクリプトを停止する。 *: Webブラウザのタブを強制終了する。 *: デベロッパーツールのSourcesパネルで一時停止ボタンを使用する。 *: <br> * Node.jsでの対処 *: [Ctrl] + [C]キーでプロセスを停止する。 *: 別のターミナルから <code>kill</code> コマンドでプロセスを終了する。 *: <br> * デバッグ方法 *: ループの反復回数をカウントするカウンタ変数を追加する。 *: <code>console.log</code> でループ変数の変化を追跡する。 *: ブレークポイントを設定してステップ実行で状態を確認する。 <br> <syntaxhighlight lang="javascript"> // デバッグ用カウンタを追加した例 let i = 0; let debugCount = 0; while (someCondition) { debugCount++; console.log(`反復 ${debugCount}: i = ${i}`); if (debugCount > 1000) { console.error("無限ループの可能性を検出"); break; } // ...処理 } </syntaxhighlight> <br><br> == while系ループとfor系ループの使い分け == JavaScriptには複数のループ構文が用意されており、それぞれ適した用途がある。<br> ループ構文を適切に選択することで、ソースコードの可読性と保守性が向上する。<br> <br> <center> {| class="wikitable" |+ ループ構文の比較 ! ループ !! 初期化 !! 条件判定 !! 更新 !! 最低実行回数 !! 最適な用途 |- | while || ループ外 || ループ前 || ループ内 || 0回 || 繰り返し回数が不定なループ |- | do...while || ループ外 || ループ後 || ループ内 || 1回 || 最低1回の実行が必要なループ |- | for || ループ式内 || ループ式内 || ループ式内 || 0回 || 繰り返し回数が決まっているループ |- | for...of || 不要 (自動) || 自動 || 自動 || 0回 || イテラブルの値を順に処理するループ |} </center> <br> 各ループ構文の選択基準を以下に示す。<br> <br> <center> {| class="wikitable" |+ ループ構文の選択基準 ! ループ構文 !! 選択基準 |- | while文 || 繰り返し回数が事前に不定な場合<br>特定の条件が変化するまで繰り返す場合<br>データを順次取得しながら処理する場合 |- | do...while文 || ループ本体を最低1回は必ず実行する必要がある場合<br>ユーザ入力の検証<br>メニュー表示<br>リトライ処理 |- | for文 || 繰り返し回数が事前にわかっている場合<br>インデックスを使った配列へのアクセスが必要な場合<br>複数のカウンタ変数を同時に制御する場合 |- | for...of文 || 配列<br>文字列<br>Map、Set等のイテラブルを順に処理する場合<br>インデックスが不要で値のみを扱う場合 |} </center> <br> <code>for...of</code> の詳細については、[[JavaScriptの基礎 - 反復処理(for文)]]のページを参照すること。<br> <br><br> == 関連情報 == * [[JavaScriptの基礎 - 変数宣言]] *: let / const / varの宣言方法、スコープ、ホイスティング * [[JavaScriptの基礎 - プリミティブ型]] *: 7つのプリミティブ型、typeof演算子、型の自動変換 * [[JavaScriptの基礎 - 比較演算子と論理演算子]] *: === / ==の違い、短絡評価、Null合体演算子、オプショナルチェーン * [[JavaScriptの基礎 - 反復処理(for文)]] *: for文、for...of、for...in、使い分け <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Web]]
JavaScriptの基礎 - 反復処理(while文)
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse