JavaScriptのループと反復処理

プログラミングにおいて、ループ文と反復処理は非常に重要な概念です。

ループ文は、指定した回数だけコードを繰り返し実行するために使われ、特に大量のデータ処理や繰り返しの操作に役立ちます。

本記事では、これらのループ文の基本から応用までを詳しく解説し、最適な反復処理の方法を習得できるようにします。

ループ文をマスターすることで、コードの見通しが良くなり、効率的かつ効果的にプログラムを構築することが可能になります。

さあ、ループ文と反復処理の世界に足を踏み入れてみましょう。

JavaScriptのループ文

JavaScriptでは、for文、while文、do...while文、そしてfor...infor...ofといったさまざまなループ構文が存在します。

それぞれのループ文には固有の特性と適用範囲があり、適切な選択と使用が求められます。

for文

for文は、特定の回数だけ繰り返し処理を行うために使用されるループ構文です。

繰り返し処理を効率的に行うことで、同じコードを何度も書く手間を省くことができます。

  • 初期化式:ループが開始される前に一度だけ実行される式。通常、カウンタ変数を初期化します。
  • 条件式:各ループの繰り返し前に評価される式。条件式が真である限り、ループが実行されます。
  • 増減式:各ループの繰り返しの後に実行される式。通常、カウンタ変数を増減します。
for (初期化式; 条件式; 増減式) {
  // 繰り返し実行されるコード
}

for (let i = 0; i < 5; i++) {
  console.log(i);
}

/* 実行結果 */
// 0
// 1
// 2
// 3
// 4 

for文をネストする

for文は、他のfor文の内部にネストすることもできます。

これにより、多次元配列の処理など、複雑な繰り返し処理を行うことができます。

for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    console.log(`i = ${i}, j = ${j}`);
  }
}

/*  実行結果  */
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 1, j = 0
i = 1, j = 1
i = 1, j = 2
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2

for文と配列

for文を使用すると、配列の要素を繰り返し処理することが簡単にできます。

let fruits = ["apple", "banana", "cherry"];

for (let i = 0; i < fruits.length; i++) {
    console.log(fruits[i]);
}
 /*  実行結果  */// apple // banana // cherry

for…in文

for...in 文は、オブジェクトのプロパティを列挙するために使用されます。

これは特定のオブジェクトのすべての列挙可能なプロパティを反復処理するのに便利です。

ただし、配列のインデックスを反復処理するためにも使えますが、これは一般的には推奨されません。

以下に、 for...in 文の基本的な構文と使用例を示します。

for (変数 in オブジェクト) {
  // 繰り返し実行されるコード
}

変数: 各反復ごとにオブジェクトのプロパティ名が代入される変数。

オブジェクト: プロパティを反復処理する対象のオブジェクト。

使用例

以下の例では、オブジェクトpersonのすべてのプロパティを列挙し、その値を出力しています。

let person = {
  name: "Alice",
  age: 25,
  city: "Tokyo"
};

for (let key in person) {
  console.log(key + ": " + person[key]);
}
// 出力:
// name: Alice
// age: 25
// city: Tokyo

この例では、personオブジェクトの各プロパティ(nameagecity)が反復処理され、その名前と値が出力されます。

配列のインデックスを反復処理する

for...in文は配列にも適用できますが、配列のインデックスを列挙するための方法としては一般的に推奨されません。

for...of文や標準のfor文を使うほうが適切です。

let fruits = ["Apple", "Banana", "Cherry"];

for (let index in fruits) {
  console.log(index + ": " + fruits[index]);
}
// 出力:
// 0: Apple
// 1: Banana
// 2: Cherry

この例では、配列fruitsのインデックス(012)が列挙され、それぞれの要素が出力されます。

しかし、これは特に配列のための一般的な使い方ではありません。

配列への使用はfor...in文は配列のインデックスを反復処理するためにも使えますが、予期しない結果を引き起こす可能性があるため、配列に対してはfor...of文や標準のfor文を使用することが推奨されます。

プロトタイプチェーン

for...in文はオブジェクトのプロトタイプチェーン上の列挙可能なプロパティも列挙します。

そのため、独自のプロパティのみを列挙したい場合は、hasOwnPropertyメソッドを使ってフィルタリングする必要があります。

for (let key in object) {
  if (object.hasOwnProperty(key)) {
    // 独自のプロパティのみを処理
  }
}

for…of文

for...of 文は、反復可能なオブジェクト(配列、文字列、マップ、セットなど)の各要素に対して反復処理を行うための構文です。

for...of は、配列や他のコレクションに対して反復処理を行うための直感的で簡潔な方法を提供します。

for (変数 of 反復可能オブジェクト) {
  // 繰り返し実行されるコード
}

変数: 反復処理の各回で反復可能オブジェクトから取得される要素が代入される変数。

反復可能オブジェクト: 配列や文字列など、反復処理の対象となるオブジェクト。

配列の反復処理

配列の各要素を順番に出力するfor...of文の例です。

let fruits = ["Apple", "Banana", "Cherry"];

for (let fruit of fruits) {
  console.log(fruit);
}
// 出力:
// Apple
// Banana
// Cherry

この例では、fruits配列の各要素が順番にfruit変数に代入され、ループ内で出力されます。

文字列の反復処理

文字列の各文字を順番に出力するfor...of文の例です。

let str = "Hello";

for (let char of str) {
  console.log(char);
}
// 出力:
// H
// e
// l
// l
// o

この例では、文字列strの各文字が順番にchar変数に代入され、ループ内で出力されます。

マップの反復処理

マップの各エントリーを反復処理するfor...of文の例です。

let map = new Map([
  ["name", "Alice"],
  ["age", 25],
  ["city", "Tokyo"]
]);

for (let [key, value] of map) {
  console.log(key + ": " + value);
}
// 出力:
// name: Alice
// age: 25
// city: Tokyo

この例では、mapオブジェクトの各エントリーが順番に[key, value]に代入され、ループ内で出力されます。

セットの反復処理

セットの各要素を反復処理するfor...of文の例です。

let set = new Set(["Apple", "Banana", "Cherry"]);

for (let item of set) {
  console.log(item);
}
// 出力:
// Apple
// Banana
// Cherry

この例では、setオブジェクトの各要素が順番にitem変数に代入され、ループ内で出力されます。

while文

while文は、指定した条件が真である間、繰り返し処理を行うためのループ構文です。

繰り返しの回数が事前に決まっていない場合や、条件に応じて動的に変化する場合に適しています。

while (条件式) { 
  // 条件式が真である間、繰り返し実行されるコード
}
let count = 0;

while (count < 5) {
    console.log(count);
    count++;
}

/*  実行結果  */
// 0
// 1
// 2
// 3
// 4

while文を使用する際には、条件が偽になるタイミングを適切に設定しないと無限ループになる可能性があります。

無限ループはプログラムの停止やフリーズを引き起こすため、必ず条件が偽になるような条件を設定しましょう。

// 無限ループの例(実行に注意)
while (true) {
    console.log("このコードは永遠に実行されます。");
}

do…while文

do...while文は、while文と似ていますが、少なくとも一度はコードブロックを実行することを保証します。

条件の評価はループの後に行われます。


do {
    // 少なくとも一度は実行されるコード
} while (条件式);

let count = 0;

do {
    console.log(count);
    count++;
} while (count < 5);

// 0
// 1
// 2
// 3
// 4

while文とdo…while文の違い

while文は、条件が真であるかどうかを評価してからループを実行しますが、do...while文は少なくとも一度はコードブロックを実行し、その後に条件を評価します。

この違いにより、do...while文は、少なくとも一回はループ内の処理を実行する必要がある場合に便利です。

// while文
let count1 = 5;

while (count1 < 5) {
    console.log("while:", count1);
    count1++;
}

// do...while文
let count2 = 5;

do {
    console.log("do...while:", count2);
    count2++;
} while (count2 < 5);

上記の例では、count1 は最初から5なので、while文は一度も実行されません。

一方、count2do...while文で少なくとも一度は実行され、「do…while: 5」が表示されます。

break文

break文は、ループの実行を中断し、ループから抜け出すために使用されます。

break文が実行されると、ループの残りの反復をスキップし、ループの直後のコードに処理が移ります。

for (let i = 0; i < 10; i++) {
    if (i === 5) {
        break;
    }
    console.log(i);
}

上記の例では、i が5に達した時点でループが終了し、それ以降の反復は実行されません。

ラベルを使用する

break文は、現在のループを完全に終了し、ループの後に続くコードを実行します。

ラベルを使用すると、入れ子になったループの特定のループを終了することができます。

通常のbreakcontinue文では最も内側のループしか制御できませんが、ラベルを使うことで特定の外側のループに対しても操作が可能になります。

outerLoop: for (let i = 0; i < 5; i++) {
  for (let j = 0; j < 5; j++) {
    if (i === 2 && j === 2) {
      break outerLoop; // `outerLoop`というラベルの付いたループを終了
    }
    console.log(`i = ${i}, j = ${j}`);
  }
}

この例では、ijが両方とも2になったとき、outerLoopというラベルの付いた外側のループが終了します。

これにより、特定の条件に基づいて複数のループを一度に制御できるのです。

ラベルがない場合、通常のbreak文は最も内側のループを終了するだけです。例えば

for (let i = 0; i < 5; i++) {
  for (let j = 0; j < 5; j++) {
    if (j === 2) {
      break; // 内側のループだけが終了する
    }
    console.log(`i = ${i}, j = ${j}`);
  }
}

この例では、j2になった時点で内側のループが終了しますが、外側のループは続行されます。

countinue文

continue文は、現在の反復をスキップし、次の反復に移るために使用されます。

continue文が実行されると、その反復の残りのコードは実行されず、次の反復が開始されます。

let count = 0;

while (count < 10) {
    count++;
    if (count % 2 === 0) {
        continue;
    }
    console.log(count);
}

/* 実行結果 */
// 1
// 3
// 5
// 7
// 9

上記の例でも、count が偶数のときにcontinue文が実行され、console.log(count) はスキップされます。

ラベルを使用する

continue文は、現在の反復を終了し、次の反復にスキップします。

ラベルを使用すると、入れ子になったループの特定のループにスキップすることができます。

outerLoop: for (let i = 0; i < 5; i++) {
  for (let j = 0; j < 5; j++) {
    if (j === 3) {
      continue outerLoop; // `outerLoop`というラベルの付いた次の反復にスキップ
    }
    console.log(`i = ${i}, j = ${j}`);
  }
}

この例では、j3になったとき、outerLoopというラベルの付いた外側のループの次の反復にスキップします。

出力結果は以下の通りです。

i = 0, j = 0
i = 1, j = 1
i = 2, j = 2
i = 3, j = 2
i = 4, j = 2

各内側ループのj3になると、outerLoopラベルの付いた外側のループの次の反復にスキップします。

まとめ

ループと反復処理は、プログラムにおいて効率的に繰り返し処理を行うための重要な構造です。

for文、while文、do...while文は、特定の条件が満たされるまでコードを繰り返し実行するための基本的なループ構文です。

これらを使うことで、同じ処理を何度も手作業で書く必要がなくなり、 複雑な処理をシンプルに実装できるようになります。

ループと反復処理をマスターすることで、より高度なプログラミング技術を身につけることができます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です