LoginSignup
9
6

More than 5 years have passed since last update.

自分がJavaScript(ES5)のfor(var i = 0; i < array.length; i++)が嫌いな理由

Last updated at Posted at 2016-02-25

JavaScript歴4ヶ月ぐらいですが頑張って書こうと思います。
Java出身の人がやりがちな書き方を見ていこうと思います。

for(var i = 0; i < array.length; i++)の嫌いなところ

forの中で毎回length参照してるから遅くなるよねー
って話ではないです。(それももっともだけど!

(2016/11/16)追記:array.lengthについて
JITコンパイラさんが「固定値を返すメソッドに何度もアクセスする場合」には固定値として扱うように最適化されるため速度的にはあまり問題にならないみたいです。
参考資料:Demystifying (JavaScript) Engines

(簡単に言うとスコープ意識しましょうねっていう話です)
自分も初めの頃、for内宣言を書いていました。

サンプル

例えば次のようなコードがあったとします。

forTrap.js
var i = 3;
(function () {
    console.log('before-for:' + i);
    for (var i = 0; i < 10; i++) {
        console.log('in-for:' + i);
    }
    console.log('after-for:' + i);
} ());

このコードのafter-for:のあとの数値はどうなるでしょう?

このコードを実行したときに、after-for:3が表示されると思った方…

危ない!

JavaScriptおじさんに捕まってしまいますよ!

JavaScriptのスコープを思い出してください。
JavaScriptのスコープは{}ではなくfunction(){}なので、宣言したiはfor文が終わっても残ります。
つまりiをループ変数としたfor文が2回でてくると2重宣言になるわけです。
これはあんまりよろしくないですね。

ということで、答えはafter-for:10が出力されます。

そんなこたぁわかってるよ!ってみなさん
では、before-for:では何が出力されるでしょう?
今度こそ3…?

危ないっ!

JavaScriptおじさん講習会が始まっちゃいますよ!

答えは3ではなくundefinedです。
JavaScriptの関数内でグローバル変数と同じ変数名の変数を宣言した場合、
関数内ではもちろんローカル変数が参照されます。
しかし、下の行で宣言しても先頭で宣言された扱いになります。
俗に言う「変数の巻き上げ」ってやつですね。

実はさっきのコードは

forTrap2.js
var i = 3;
(function () {
    var i; //変数の巻き上げ
    console.log('before-for:' + i);
    for (i = 0; i < 10; i++) {
        console.log('in-for:' + i);
    }
    console.log('after-for:' + i);
} ());

と同じ動きとなるのでした。

ちなみに全部の出力結果(IE11)
for.png

まとめ

見た目と動作が違うと後でハマることがあるので、自分は見た目と動きは同じにしたいと思ってます。
(レガシーコードもりもりのJavaScriptを浴びたことがあるので…)
というわけで変数の宣言は関数の先頭で行い、for内での宣言はしないようになりました。
まぁ、ループ変数名が外のスコープと重なってハマるなんてなかなかなさそうですけどね~。

9
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6