2023年2月8日

ループ: while と for

繰り返し処理は頻繁に必要になります。

例えば、1つずつリストから商品を出力するような場合や、単に1から10の数値それぞれに同じコードを実行する場合などです。

ループ は複数回同じコードを繰り返す手段です。

for…of と for…in ループ

上級者向けのちょっとしたお知らせです。

この記事は基本的なループ: while, do..whilefor(..;..;..) のみの説明をしています。

他の種類のループを検索してこの記事にたどり着いたのであれば、以下を参照してください。

  • オブジェクトプロパティのループは for…in です。
  • 配列や反復可能オブジェクトに対するループは for…ofiterables です。

それ以外の場合は、続けて読んでみてください。

“while” ループ

while ループは次の構文になります:

while (condition) {
  // code
  // いわゆる "ループ本体" です
}

conditiontrue の間、ループの本体の code が実行されます。

例えば、以下のループは i < 3 の間、i を出力します:

let i = 0;
while (i < 3) { // 0, 次に 1, 次に 2 を表示
  alert( i );
  i++;
}

ループ本体の1回の実行は イテレーション と呼ばれます。上の例のループは3回イテレーションします。

もしも上の例に i++ がない場合、ループは (理論上は) 永遠に繰り返されます。実際には、ブラウザはこのようなループを止める方法を提供しており、サーバサイドJavaScriptではそのプロセスを殺すことができます。

比較に限らず、どんな式や変数もループの条件にすることができます。条件は while によって評価され、真偽値に変換されます。

たとえば、while (i != 0) をより短く書く方法としてwhile (i)があります:

let i = 3;
while (i) { // i が 0 になったとき、条件が偽になり、ループが止まります
  alert( i );
  i--;
}
本体が1行の場合、括弧は必須ではありません

ループの本体が単一の文である場合、括弧{…}を省略することができます:

let i = 3;
while (i) alert(i--);

“do…while” ループ

do..while 構文を使うことで、条件チェックをループ本体の 下に 移動させることができます。:

do {
  // loop body
} while (condition);

ループは最初に本体を実行した後、条件をチェックし、条件が真である間、本体の実行を繰り返します。

例:

let i = 0;
do {
  alert( i );
  i++;
} while (i < 3);

この構文の形式は、条件が真になるかどうかに関わらず、少なくとも1度 はループ本体を実行したい場合にのみ使用されるべきです。通常は他の形式が好まれます: while(…) {…}

“for” ループ

for ループは最も使われるものの1つです。

このようになります:

for (begin; condition; step) {
  // ... loop body ...
}

例でこれらのパーツの意味を学びましょう。下のループは i0 から 3 になるまで(3 は含みません)、 alert(i) を実行します。:

for (let i = 0; i < 3; i++) { // 0, 次に 1, 次に 2 を表示
  alert(i);
}

for 文を部分的に調べてみましょう:

パート
begin i = 0 ループに入ると1度実行されます。
condition i < 3 すべてのループのイテレーションの前にチェックされます。条件が偽の場合、ループを停止します。
step i++ 各イテレーションで、条件チェックの前に本体の後に実行されます。
body alert(i) 条件が真の間繰り返し実行されます。

一般的なループアルゴリズムは次のように動作します:

begin を実行
→ (if condition → body を実行し step を実行)
→ (if condition → body を実行し step を実行)
→ (if condition → body を実行し step を実行)
→ ...

つまり、begin を1度実行し、その後、各 condition の評価の後、bodystep が実行されるという繰り返しになります。

もしループに慣れていない場合は、上の例に戻って、紙の上でステップ毎にどのように動作するかを再現してみると理解しやすいでしょう。

これが今のケースで正確に起こっていることです:

// for (let i = 0; i < 3; i++) alert(i)

// begin を実行
let i = 0
// if condition → body を実行し step を実行
if (i < 3) { alert(i); i++ }
// if condition → body を実行し step を実行
if (i < 3) { alert(i); i++ }
// if condition → body を実行し step を実行
if (i < 3) { alert(i); i++ }
// ...終わり, 今 i == 3 なので
インライン変数宣言

ここで “カウンタ” 変数 i はループの中で正しく宣言されます。それは “インライン” 変数宣言と呼ばれます。このような変数はループの中でだけ見えます。

for (let i = 0; i < 3; i++) {
  alert(i); // 0, 1, 2
}
alert(i); // エラー, そのような変数はありません

変数を宣言する代わりに、既存のものを使うこともできます:

let i = 0;

for (i = 0; i < 3; i++) { // 既存の変数を使用
  alert(i); // 0, 1, 2
}

alert(i); // 3, ループの外で宣言されているので見える

一部分の省略

for の一部分は省略することができます。

例えば、ループの最初で何もする必要がなければ、begin を省略できます。

このようになります:

let i = 0; // すでに i を宣言し代入済み

for (; i < 3; i++) { // "begin" 不要
  alert( i ); // 0, 1, 2
}

同じように step パートも除去することができます。:

let i = 0;

for (; i < 3;) {
  alert( i++ );
}

ループは while (i < 3) と同じになりました。

実際にはすべてを除くこともできます。それは無限ループになります:

for (;;) {
  // 制限なしで繰り返し
}

for