WEBサービス創造記

WEBサービスを作ったり保守したりしてる人のメモブログです。

JavaScriptでの変数の巻き上げ

      2015/07/22

変数の巻き上げ(hoisting)について

JavaScriptでは実装次第では「変数の巻き上げ(hoisting)」というものが発生します。

例えば、下記のコードを見てください。

var hoge = "global";

function func () {
  alert(hoge);
  var hoge = "local";
  alert(hoge);
}

func();

上記の結果は最初のアラートでグローバルスコープで定義されているhogeの値である”global”が表示され、次のアラートでローカルスコープのhogeの値である”local”が表示されるように思われます。
しかし、実際は最初のアラートではundefined, 次のアラートでは”local”がそれぞれ表示されます。

このような挙動のことは「変数の巻き上げ(hoisting)」と呼ばれています。

JavaScriptでは関数内で定義されている変数は関数内でのみ有効となるローカル変数となります。
一方関数の外で定義されている変数(上記コードでは`var hoge = “global”;`)はどこでも使用できる変数(他の言語で言ういわゆるグローバルスコープ)となりますが、関数内で同じ名前のローカル変数がある場合はローカル変数の方が有効になります。

この法則から考えると上記のように”global”, “local”の表示になると思われるのですが、JavaScriptではこれに加え以下のような決まりがあるので、”undefined”, “local”という表示となります。

関数内で宣言されたローカル変数は、すべてその関数の先頭で宣言されたものとみなされる。 

上記コードでは最初のアラートの後でローカル変数の定義が行われていますが、上記の巻き上げの規則によって実際は下記のようなコードに変換されて実行されていることになります。

var hoge = "global";

function func () {
  var hoge;

  alert(hoge);
  var hoge = "local";
  alert(hoge);
}

func();

ただし、関数の先頭で行われるのは宣言のみで後で行った値の代入までは行われません。

このように変数の巻き上げによって意図しない振る舞いにならないようにローカル変数は関数の先頭でまとめて宣言したほうがいいように思えました。

以上、JavaScriptでの変数の巻き上げでした。

参考資料

 - JavaScript , , , ,