JavaScriptのループ処理(for, while)

2025-07-28

ループ処理の基本概念

ループ処理は、特定の条件が満たされている間、同じ処理を繰り返し実行するための仕組みです。JavaScriptには主に以下のループ構文があります:

  • forループ
  • whileループ
  • do...whileループ
  • for...inループ(オブジェクト用)
  • for...ofループ(イテラブルオブジェクト用)

forループ

基本的なforループ

for (let i = 0; i < 5; i++) {
  console.log(i); // 0, 1, 2, 3, 4
}

構成要素

  1. 初期化式 (let i = 0): ループ開始時に1回だけ実行
  2. 条件式 (i < 5): 各ループ前に評価され、trueなら実行
  3. 更新式 (i++): 各ループ後に実行

応用的なforループ

// 複数の変数を初期化
for (let i = 0, j = 10; i < j; i++, j--) {
  console.log(`i:${i}, j:${j}`);
}

// 要素をスキップ
for (let i = 0; i < 10; i++) {
  if (i % 2 === 0) continue; // 偶数はスキップ
  console.log(i); // 1, 3, 5, 7, 9
}

// ループを途中で終了
for (let i = 0; i < 10; i++) {
  if (i === 5) break; // iが5になったら終了
  console.log(i); // 0, 1, 2, 3, 4
}

whileループ

基本的なwhileループ

let count = 0;
while (count < 5) {
  console.log(count); // 0, 1, 2, 3, 4
  count++;
}

無限ループとその回避

// 意図しない無限ループの例
let x = 0;
while (x < 5) {
  console.log(x);
  // x++を忘れていると無限ループ
}

// 意図的な無限ループ(抜け道あり)
while (true) {
  let input = prompt('「exit」と入力してください');
  if (input === 'exit') break;
}

do…whileループ

let result;
do {
  result = prompt('「yes」と入力してください');
} while (result !== 'yes');

特徴

  • 条件式が後ろにあるため、最低1回は実行される
  • ユーザー入力の確認などに適している

ループ制御文

break文

for (let i = 0; i < 10; i++) {
  if (i === 5) {
    break; // ループを抜ける
  }
  console.log(i); // 0, 1, 2, 3, 4
}

continue文

for (let i = 0; i < 10; i++) {
  if (i % 2 === 0) {
    continue; // 次のループに進む
  }
  console.log(i); // 1, 3, 5, 7, 9
}

ループのネスト

// 九九の表を作成
for (let i = 1; i <= 9; i++) {
  let row = '';
  for (let j = 1; j <= 9; j++) {
    row += `${i * j}\t`;
  }
  console.log(row);
}

配列の反復処理

伝統的なforループ

const fruits = ['apple', 'banana', 'orange'];
for (let i = 0; i < fruits.length; i++) {
  console.log(fruits[i]);
}

for…ofループ(ES6)

for (const fruit of fruits) {
  console.log(fruit);
}

パフォーマンスの最適化

  1. ループ外でlengthをキャッシュ:
   for (let i = 0, len = array.length; i < len; i++) {
     // 処理
   }
  1. 逆順ループ:
   for (let i = array.length - 1; i >= 0; i--) {
     // 処理
   }
  1. ループの展開:
   for (let i = 0; i < array.length; i += 4) {
     process(array[i]);
     process(array[i+1]);
     process(array[i+2]);
     process(array[i+3]);
   }

ループのベストプラクティス

  1. 適切なループを選択:
  • 回数が決まっている → for
  • 条件による繰り返し → while / do...while
  • 配列の反復 → for...of または forEach()
  1. 無限ループを避ける:
  • 必ず終了条件を確認
  • while(true)には必ずbreakを用意
  1. 可読性を重視:
  • 複雑なループはコメントを追加
  • ネストは3段階までが目安
  1. 副作用を最小限に:
  • ループ内で外部変数を変更しない
  • 可能なら関数型プログラミングを採用

演習問題

初級問題(3問)

  1. 次のforループをwhileループに書き換えなさい。
   for (let i = 0; i < 5; i++) {
     console.log(i);
   }
  1. whileループの危険性を説明し、修正してください。

以下のコードは、1から10までの数字を順番に出力することを意図していますが、実行するとプログラムが止まりません。なぜこのような動作になるのか説明し、正しく修正してください。

   let i = 1;

    while (i <= 10) {
        console.log(i);
    }
  1. 次のコードの出力結果は?
   let x = 0;
   while (x < 3) {
     console.log(x);
     x++;
   }

中級問題(6問)

  1. 次のコードの間違いを指摘し、修正しなさい。
   for (let i = 10; i > 0; i--) {
     console.log(i);
   }
   console.log('最後のiの値:', i);
  1. 次の配列の要素を逆順に出力するプログラムを書きなさい。
   const colors = ['red', 'green', 'blue', 'yellow'];
  1. 1から100までの数字で、偶数のときは 'Even'、奇数のときは 'Odd' を出力しなさい。それ以外は何も出力しなくてよい。
  2. 次のコードの出力結果とその理由を説明しなさい。
   for (let i = 0; i < 5; i++) {
     if (i === 2) continue;
     if (i === 4) break;
     console.log(i);
   }
  1. ネストされたループを使用して、次のパターンを出力するプログラムを書きなさい。
   *
   **
   ***
   ****
   *****
  1. 次のオブジェクトのプロパティ名と値をfor...inループを使って表示しなさい。
   const person = {
     name: '山田太郎',
     age: 30,
     occupation: 'エンジニア'
   };

上級問題(3問)

  1. 次の2次元配列のすべての要素の合計を計算するプログラムを書きなさい。
const matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ];
  1. 素数判定プログラムを作成しなさい。引数として与えられた数が素数かどうかを判定する関数isPrimeを実装しなさい。
  1. フィボナッチ数列の最初の20項を配列として生成するプログラムを書きなさい。

フィボナッチ数列は次のように定義されます。最初の2つの数字が1で、それ以降の数字が前の2つの数字の和で表される数列のことです。具体的には、1, 1, 2, 3, 5, 8, 13, 21, 34, … のように続きます。

F₀ = 0

F₁ = 1

Fₙ = Fₙ₋₁ + Fₙ₋₂ (n ≥ 2)

解答例

初級問題解答

  1. forループをwhileループに書き換え。
   let i = 0;
   while (i < 5) {
     console.log(i);
     i++;
   }
  1. whileループの危険性と修正

カウンター変数iをインクリメントしなければ無限ループする。

    let i = 1;

    while (i <= 10) {
        console.log(i);
        i++;  // カウンターをインクリメントしてループを終わらせる
    }
  1. コードの出力結果
   0
   1
   2

中級問題解答

  1. 間違いと修正
   // 間違い: ループ外でiを参照しようとしている(ブロックスコープ)
   // 修正例1(letをvarに変更):
   for (var i = 10; i > 0; i--) {
     console.log(i);
   }
   console.log('最後のiの値:', i);

   // 修正例2(ループ外で変数を宣言):
   let j;
   for (j = 10; j > 0; j--) {
     console.log(j);
   }
   console.log('最後のjの値:', j);
  1. 配列の逆順出力
   for (let i = colors.length - 1; i >= 0; i--) {
     console.log(colors[i]);
   }
  1. 偶数 'Even'と奇数 'Odd' 
for (let i = 1; i <= 100; i++) {
  if (i % 2 === 0) {
    console.log('Even');
  } else {
    console.log('Odd');
  }
}
  1. コードの出力結果とその理由
0
1   // i=2のときcontinueでスキップ
3   // i=4のときbreakでループ終了
    for (let i = 0; i < 5; i++) {
        if (i === 2) continue;  // i=2のときcontinueでスキップ
        if (i === 4) break;     // i=4のときbreakでループ終了
        console.log(i);
    }
  1. パターンを出力するプログラム
   for (let i = 1; i <= 5; i++) {
     let stars = '';
     for (let j = 0; j < i; j++) {
       stars += '*';
     }
     console.log(stars);
   }
  1. オブジェクトのプロパティ名と値をfor...inループを使う
   for (const key in person) {
     console.log(`${key}: ${person[key]}`);
   }

上級問題解答

  1. 2次元配列の合計を計算するプログラム
let total = 0;
for (let i = 0; i < matrix.length; i++) { 
    for (let j = 0; j < matrix[i].length; j++) { 
         total += matrix[i][j]; 
    } 
} 
console.log(total); // 45
  1. 素数判定判定プログラム
function isPrime(num) { 
    if (num <= 1) return false; 
    if (num === 2) return true; 
    for (let i = 2; i <= Math.sqrt(num); i++) { 
        if (num % i === 0) return false; 
    } return true; 
}
  1. フィボナッチ数列20項を配列として生成するプログラム
const fibonacci = [0, 1]; 
for (let i = 2; i < 20; i++) { 
    fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2]; 
} 
console.log(fibonacci);