繰り返し処理 for文、while文などの基本 [Java Script]


繰り返し処理

プログラミングのコードを書いていると、同じ処理を数回繰り返して処理を行いたい時があります。

例えば、

:::note warn
 
 ある処理を１０回繰り返し行うように書きたい。
 
:::

なので、１０回同じ処理を書く！
```js
console.log(1);
console.log(2);
console.log(3);
console.log(4);
console.log(5);
console.log(6);
console.log(7);
console.log(8);
console.log(9);
console.log(10);
```
```text: 出力結果：
1
2
3
4
5
6
7
8
9
10
```

これは、読みにくいコードになってしまうし、とても非効率です・・・

そのために、各プログラミング言語には
**繰り返し処理**というものが存在し、それを活用することで、
複数の処理を１つの式として短縮して書くことができます。

#### 例：
・console.logの出力を１つの式でかける。
・配列の中のすべての数字の合計値を求める。

また、ループの中には
for、while、for...ofなど様々な種類があるので一つ一つ見ていこうと思います。

## 目次：

- [forループ](#forループ)
- [無限ループに※注意](#無限ループに注意)
- [配列の中のループ処理](#配列の中のループ処理)
- [ループのネスト](#ループのネスト)
- [for...ofループ](#forof-ループ)
- [whileループ](#whileループ)
- [break文](#break文)
- [まとめ](#まとめ)

## forループ

for文では指定した回数だけ繰り返し処理を行うことができます。
事前にどんな処理を何回繰り返すのかを決めておくのが一般的です。

#### for文の書式

for (
    「初期化式」;
    「条件式」;
    「増減式」
)

:::note info

for文では３つの引数を渡してあげるのが一般的です。

初期値 : 繰り返す回数の初期値
条件式 : 繰り返しを継続する条件
増減式 : 「初期値」を増減する式

:::

#### 例１：

先ほど、上の例で表示した１〜１０までのconsole.logで出力した数字をforループ文を使って書いてみると
２、３行で書くことができます！

```js
for ( let i = 0; i <= 10; i++){
    console.log(i);
}
```
```text:出力結果
1
2
3
4
5
6
7
8
9
10
```
for文で書くと、見やすく、わかりやすく書くことができますね。

また、上に書いた式を先ほどの項目に当てはめてみると、次のようになります。

初期値 : let i = 0;
条件式 : i <= 10;
増減式 : i++

この例では、初期値「i」に対して0を代入し、条件式となる「i <= 10」(iが10になるまで)が成立(true)している場合はそのまま繰り返し処理を実行します。

そして、増減式の式にあるように初期値「i」を足していき、条件式が成立しなくなる「i <= 10」(iが10になるまで)「false」まで繰り返し処理を行うのがfor文になります。

#### 例２：

条件式を変更することで、取ってくる値を変更することも可能です。

２〜２０までの偶数の値を繰り返し出力するには？


```js
for ( let i = 2; i <= 20; i += 2){
    console.log(i);
}
```
```text:出力結果
2
4
6
8
10
12
14
16
18
20
```
初期値 : let i = 2;
条件式 : i <= 20;
増減式 : i += 2

この例では、初期値「i」に対して2を代入し、条件式となる「i <= 20」(iが20になるまで)が成立(true)している場合はそのまま繰り返し処理を実行します。

そして、増減式の式にあるように初期値「i」に増減式の数値「+2」を足していき、条件式が成立しなくなる「i <= 20」(iが20になるまで)「false」まで繰り返し処理を行う。

このように、初期値を２にして増減式の値を+=2にすることにより、偶数の値を取得する繰り返し文を書くこともできます。
***
### 無限ループに※注意

永遠に終了しないループのことを無限ループと呼びます。
これが発生すると多くの場合、ブラウザの画面が固まってしまいひどい場合は、強制終了しなければならない可能性もあります。

なので、

::: note warn
ループを考える時の、**終了条件**には注意すること。
:::

#### 例：
```js
for (let i = 20; i >= 0; i++) {
    console.log(i);
}
```
```text:出力結果
20
21
22
・・・
```
初期値 : let i = 20;
条件式 : i >= 0;
増減式 : i ++ 

この例では、初期値「i」に対して20を代入し、条件式となる「i >= 0」(iが0になるまで)が成立(true)している場合はそのまま繰り返し処理を実行します。

そして、増減式の式にあるように初期値「i」に増減式の数値「+1」を足していき、条件式が成立しなくなる「i >= 0」(iが0になるまで)「false」まで繰り返し処理を行う。

この場合、
初期値が20で1を+し続けるわけですから、当然条件がいつまでもfalseになりません。

このような処理を実行してしまわないように注意しましょう!

::: note warn
また、大体がケアレスミスな場合が多いです。

上記のコードの場合、条件式を「i--」とiを1づつ引いていく式にすれば問題なく処理が終わります。

なので、間違えても慌てずに修正するようにしましょう。
:::

## 配列の中のループ処理

ここまでで、繰り返し処理の基本は理解できたかと思います。
しかし、カウンターのような数を数えることが一体なんの役に立つのでしょうか？

実は、このカウンターのような性質を使い、配列の中身を順番に見ていくことができます。



配列のインデックスは、０から始まり、配列の長さ-1のインデックスまでありました。

この性質を使い、条件式に配列の長さを指定することで、配列の中身を出力することができます。
```js
const animals = ["lion","tiger","bird"];

for (let i = 0; i < animals.length; i++) {
    console.log(i, animals[i]);
}
```

```text:出力結果：
0 "lion"
1 "tiger"
2 "bird"
```

初期値 : let i = 0;
条件式 : i < animals.length「上の例の場合３」;
増減式 : i ++ 

この例では、初期値「i」に対して0を代入し、条件式となる「i < animals.length」(iがanimalsのlengthよりも小さい間)が成立(true)している場合はそのまま繰り返し処理を実行します。

そして、増減式の式にあるように初期値「i」に増減式の数値「+1」を足していき、条件式が成立しなくなる「i < animals.length」(iがanimalsのlengthの長さより小さくなったら)「false」まで繰り返し処理を行う。

この場合、
animals.length３よりも小さい間

::: note info

・　i 「インデックス」の**数字**を出力する
・ animals[ i ]「animalsのインデックスに対応した**配列の中身**を出力する。」
:::

## ループのネスト

ループはネスト(入れ子)することもできます。

ネストする場合、
外側のループが一回走るごとに、内側のループが全て走ります。
なので、処理の数が多くなってしまう点に注意しましょう。

#### 例：

* 配列の中に、配列があり、それを一覧化したい場合に使用できます。

下記の例では、教室の中の席順をイメージしてください。

行と列単位でそれぞれ
１列目には３人、２列目に４人、３列目に４人の生徒がいるとします。
それぞれの列の情報と、行の生徒の名前を出力する**生徒一覧**を作成するには、どうすれば良いでしょうか？


このような場合にループ処理のネストを使うことができます。

* どのように処理を書けば良いでしょうか？

```js

const seatingChart = [
    ["田中","佐藤","山田"],
    ["伊藤","高橋","山本","吉田"],
    ["杉本","安藤","今野","後藤"]
];

for (let i = 0; i < seatingCart.length; i++) {
    console.log(seatingCart[i]);
}
```
```text:出力結果：
    ["田中","佐藤","山田"],
    ["伊藤","高橋","山本","吉田"],
    ["杉本","安藤","今野","後藤"]
```
先ほどまでのようにfor文でseatingChartに対してループを回すと、
各配列の要素がそれぞれ出力するだけになってしまいます・・・

これでは意図した結果ではないですね。

出力したいのは、**各々の名前を一覧化**したものを出力させたいです。

そこで、ループ処理のネストを活用してみる！

```js
const seatingChart = [
    ["田中","佐藤","山田"],
    ["伊藤","高橋","山本","吉田"],
    ["杉本","安藤","今野","後藤"]
];

for (let i = 0; i < seatingChart.length; i++){
    const row = seatingCart[i];
    cosole.log(`${i + 1}行目`);
    for (let j = 0; j < row.length; j++) {
        consol.log(row[j]);
    }
}
```

```text:出力結果：
1行目
田中
佐藤
山田
２行目
伊藤
高橋
山本
吉田
３行目
杉本
安藤
今野
後藤
```

:::note info 
処理の解説

・外側のループを作成
・作成した配列のループの行の情報を**row**という変数の中に一旦保存しておく。
・rowに対して内側のループの処理を行う。
:::

#### 外側のループの処理内容

初期値 : let i = 0;
条件式 : i < seatingChart.length;
増減式 : i ++ 

この例では、初期値「i」に対して0を代入し、条件式となる「i < seatingChart.length」(iがseatingChartのlengthよりも小さい間)が成立(true)している場合はそのまま繰り返し処理を実行します。

そして、増減式の式にあるように初期値「i」に増減式の数値「+1」を足していき、条件式が成立しなくなる「i < seatingChart.length」(iがseatingChartのlengthの長さより小さくなったら)「false」まで繰り返し処理を行う。


#### 内側のループの処理内容
```js
for (let j = 0; j < row.length; j++) {
        consol.log(row[j]);
    }
```
rowの中には、行のそれぞれの情報が入っている
例： 
```js
row[0]
````
```text:出力結果
["田中","佐藤","山田"]
```
なので、このrowに対して１つ１つを出力するようにループ処理を走らせる。

この例では、初期値「i」に対して0を代入し、条件式となる「i < row.length」(iがrowのlengthよりも小さい間)が成立(true)している場合はそのまま繰り返し処理を実行します。

そして、増減式の式にあるように初期値「i」に増減式の数値「+1」を足していき、条件式が成立しなくなる「i < row.length」(iがrowのlengthの長さより小さくなったら)「false」まで繰り返し処理を行う。
## for...of ループ

for...of構文は、配列や列挙可能なオブジェクトの要素を順番に処理をしていく際に、
とても便利な構文です。

なので、先ほど学んだ配列の中のループ処理をより簡単に書くことができます。

#### for...of文の書式

for (変数 of 列挙可能オブジェクト) {
    「処理の内容」
}

#### 例：

・上記の配列のネストの時に使った例を参照。

列の情報と、行の生徒の名前を出力する**生徒一覧**を
for...ofを使った簡単な書き方で実践してみます。

```js
const seatingChart = [
    ["田中","佐藤","山田"],
    ["伊藤","高橋","山本","吉田"],
    ["杉本","安藤","今野","後藤"]
];
```

#### 通常のforループ文を使用した例：

```js
for (let i = 0; i < seatingChart.length; i++){
    const row = seatingCart[i];
    cosole.log(`${i + 1}行目`);
    for (let j = 0; j < row.length; j++) {
        consol.log(row[j]);
    }
}
```
#### for...of ループ文を使用した例：
```js
for (let row of seatingChart){
    for (let student of row) {
        consol.log(student);
    }
}
```

:::note info
処理の解説

・for...ofループを使って、rowの中に、seatingCartの配列の行を入れる。
・rowの中には３列の配列がそれぞれ入っているので、
それをさらにfor...ofループをすることで、
それぞれの名前をstudentという変数に入れる。
:::

```text:出力結果：
田中
佐藤
山田
伊藤
高橋
山本
吉田
杉本
安藤
今野
後藤
```

### for文とfor...of文の違いは？


上記の例を見てお気づきの方もいらっしゃるかと思いますが、

for文ではインデックスを出力することができました。
しかし、for...ofではインデックスを出力することができますが、
読みやすいコードで無くなってしまうため、推奨されていないようです。

そのため、インデックスを使って何かを行いたい場合はfor文を使う。
そうでない場合はfor...of文を使うといった形の使い分けがベターかと思われます。


## whileループ

while文とは、for文同様、特定の処理を複数回繰り返す際に利用します。

書式は下記の通りになります。

while (条件式) {
    「実行する文」;
}

:::note info
while文の実行は次のようになります。

１、条件式 の評価結果がtrueなら次のステップへ、falseなら終了
２、実行する文を実行
３、ステップ1へ戻る
:::

#### 例：
```js
let count = 0;
while (count < 10) {
    count++;
    cosole.log(count);
}

for (let i = 1; i <=10; i++) {
    console.log(i);
}
```
上記のwhile文とfor文の出力結果は同じものになります。

```text出力結果：
1
2
3
4
5
6
7
8
9
10
```
***
### for文とwhile文の使い分け

同じような出力結果が出るのであればどういうふうに使い分けるのが良いのでしょうか？


#### 主な使い分け方：

#### for文

あらかじめ繰り返し回数が決まっている場合に利用するとよい。

#### while文

繰り返し回数が決まっていない場合に利用するとよい。
例：
・ユーザーの入力に応じて何かを出力したい場合
・ゲーム（勝負が決まるまで繰り返したい）　など

具体的な例：

ユーザーに秘密のパスワードを入力してもらいます。
そのパスワードがもしあたっていれば、"パスワードが合っています。"と出力し、
パスワードの入力が間違っている間、プロンプトを出力し続けるロジックを書いてみます。

```js
const SECRET = "123456";

let guess = prompt("秘密のパスワードを入力してください。");

while(guess !== SECRET) {
    guess = prompt("秘密のパスワードを入力してください。");
}
console.log("パスワードが合っています。")
```

上記の例のように、

ユーザーが入力を正解しない間（!==）
ある出力を出し続ける。

というような場面でwhileループの処理を使うことができます。

## break文

break文を利用することで、特定の場所でループ処理を**強制終了**させることが可能になります。

#### 例：

ユーザーにpromptのinputを入力してもらいます。
そのinputの値を受け取ってユーザーに直接返すロジックを書きます。

<img src =https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/7e52f6d2-b573-a648-50e8-520ba723ee24.png width = 60% >




しかし、そのままでは無限ループになってしまうので、
ここでbreak文を使用したいと思います。

ユーザーがquit（やめる）
と入力するとロジックが終了するようにbreak文を書いて見たいと思います。

```js
let input = prompt("何か入力してください。");
while(true) {
    input = prompt(input);
    if (input === "quit") {
    break;
    }
}
```

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/0daacb47-981a-8935-f011-02080c68edea.png width = 60%>

quitと入力し、エンターを押すことで、
inputとquitが一致したので、breakが効くことによりロジックが終了し、画面からプロンプトを無くすことができます。

## まとめ：

まだまだfor文にはfor...inやfor...eachなど他にも重要な構文はあるのですが、今回は一旦繰り返し処理の基本と題して、ここまでのまとめとしたいと思います。

また、特にfor...of文に関しては、iterableオブジェクトしか反復処理できず、オブジェクトをfor...ofで処理を行う際には一手間加えることが必要だったりと、まだまだ奥が深いのでそういった詳細な部分はまた後日記載できればと思います。