【JavaScript】For文 VS While文　処理速度はどっちが早い？まさかの結果に...

こんにちは！
今回、Quita初投稿です。
ブログ書いたり、Noteに投稿したことはあったんですが、なんとなくQuitaは敷居が高くて、避けていました（言い訳です...笑）
どうせ書くなら、読者の方にとって価値ある情報を提供していきたいと思っていますので、ご指摘・ご感想いただけると嬉しいです！

本記事では**JavaScript**処理速度の違いについて、調べてみました。

# JavaScriptにおける処理速度の計測方法
JavaScriptには処理速度を計測する方法がいくつかあります。
代表的なものは以下の３つ

## 1. performance.now()を使った方法
今回はこちらの関数を使って計測します。
`performance.now()`はタイムスタンプを返します。
単位はミリ秒で、精度はブラウザによって異なるようですが、Firefoxでは２ミリ秒と書かれています。
[▶︎詳しくはこちら](https://developer.mozilla.org/ja/docs/Web/API/Performance/now)
どのように計測するかというと、ざっくりとこんなイメージです。

```javascript:script.js

//タイムスタンプ（開始時間）を取得
const startTime = performance.now();

//（計測対象の処理を記述）
//・・・

//タイムスタンプ（終了時間）を取得
const endTime = performance.now();

//処理時間 = タイムスタンプ（終了時間） - タイムスタンプ（開始時間）
const result = (endTime - startTime);

```


## 2. ブラウザの開発者ツール（Chromeなど）
単位が1ミリ秒。とても簡単に計測することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659719/5e16b97f-591e-9383-c3e3-9e16274b464f.png)
（イメージ）

## 3. Date.now()を使った方法
`Date.now()`は`performance.now()`の下位互換のような存在です。（処理速度の計測において）

# For文とWhile文を比較
`For`と`While` ２大ループ文の比較です。
計測条件を合わせるため、ループ文の中の処理は同じにしてあります。
（処理内容に深い意味はないので、突っ込まないでください...)

```javascript:script.js
// 処理速度を計測・コンソール出力するための関数
function measure(name, func) { //第一引数：関数名、第二引数：関数
  const startTime = performance.now(); //タイムスタンプ（開始時間）
  func(); //引数で渡された関数を実行
  const endTime = performance.now(); //タイムスタンプ（終了時間）

  const result = (endTime - startTime);
  const resultStr = result.toPrecision(4); //有効桁数を４桁に変換
  console.log(`${name}：${resultStr}`); //コンソールに出力
}

// For文
const funcFor = () => {
  const data = [];
  for(let i=1; i< 100000; i++) {
    data.push(Math.random()); //ランダムな値を配列に追加
    if(i > 1) {
      if(data[i] < data[i - 1]) {
        data[i] = data[i - 1];
      }
    }
  }
};

// While文
const funcWhile = () => {
  let i = 1;
  const data = [];
  while(i< 100000) {
    data.push(Math.random());
    if(i > 1) {
      if(data[i] < data[i - 1]) {
        data[i] = data[i - 1];
      }
    }
    i++;
  }
}

// 関数呼び出し
measure('For文', funcFor);
measure('While文', funcWhile);
```

### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659719/e5871b84-94c2-0dee-ae3a-d192f513f5e9.png)
実行ごとにブレがあるので、５回の平均値をとってみました。

|  | 1回目 | 2回目 |3回目 |4回目|5回目|平均値|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| For文  | 7.305 | 10.71  |8.690|9.995|7.645|8.869|
| While文  |9.680   |  11.84 |10.81|8.390|7.480|9.640|
単位：ミリ秒

#### ~~For文の勝利！!~~

For文とWhile文の処理速度を比較した結果
For文(平均8.869)　＜　While文（平均9.640）
For文の方が若干処理速度が早いことが分かった。

※単純な処理速度の比較です。
※素人の測定結果です

## 【追記・修正】純粋なFor文・While文で再度測定
@il9437さんコメントありがとうございます。

関数をシンプルなものに変更し、検証したところ、驚くべき結果となりました。

```scrips.js
// For文
const funcFor = () => {
  for(let i = 1e7; i; --i);
} 

// While文
const funcWhile = () => {
  let i = 1e7;
  while(--i);
}

// 測定
measure('While文', funcWhile);
measure('for文', funcFor);
```
### 結果
|  | 1回目 | 2回目 |3回目 |4回目|5回目|平均値|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| For文  | 1067 | 1081  |1063|1064|1079|1071|
| While文  | 1073  |  1068 |1067|1068|1065|1068|
単位：ミリ秒

#### ~~While文の勝利！!~~
とも言い難いです。
For文の方が早い時もあれば、While文の方が早い時もあります。
もう少し検証が必要ですね。。。

これを機に処理速度を意識したコーディングをしていきたいと思いました。

皆さんも興味があれば、色々処理速度を測って、遊んでみてください。

参考にさせてもらった記事
https://sbfl.net/blog/2017/12/01/javascript-measure-time/