ふたこと要約
var
で宣言された変数はホイスティングされるよ。
これを知らない故に、意図しない値代入とか発生しているかもだよ。
JavaScriptの巻き上げ(Hoisting)とは
その前に
JavaScriptの変数定義 var
- 関数内のどこからでも宣言することができる。
- 再宣言も可能。
varを使うとホイスティング(巻き上げ)が起こる
- どこからでも宣言できる
var
は、関数内のいかなる場所で宣言されたとしても、その関数の先頭で宣言されたのと同じように動作する。
例
var test = "test1";
function func_hoisting() {
console.log("func_hoisting-1 ", test);
// 期待値:test1, 出力: undefined
var test = "test2";
// 関数内で宣言。
console.log("func_hoisting-2 ", test); // 出力: test2
}
解説
感覚的に、最初の func_hoisting-1
では関数外で宣言した test1
が出力されると期待するが、実際は undefined
となる。
これは、関数 func_hoisting()
の2行目でtestという変数を宣言することで、この関数の先頭で var test;
と宣言されたことと同義となるため起きる現象。
つまり、func_hoisting()は以下と同じ動作をしている。
function func() {
var test; // 変数を宣言。
console.log("func-1 ", test); // 出力: undefined
var test = "test2";
console.log("func-2 ", test); // 出力: test2
}
このように、変数の宣言が関数の先頭に移動したように見えるため、巻き上げ(Hoisting)と呼ばれている。
対策(推奨しない)
関数内で利用する変数に var
をつけない
var test = "test1";
function func_not_hoisting() {
console.log("func_not_hoisting-1 ", test); // 出力: test1
test = "test2"; // varをつけずに代入
console.log("func_not_hoisting-2 ", test); // 出力: test2
}
対策
変数の宣言は適宜正しく行う。
関数の先頭で明示的に宣言しておけば、意図しない値にはならない。
function func() {
var test; // 変数を宣言。
console.log("func-1 ", test); // 出力: undefined
var test = "test2";
console.log("func-2 ", test); // 出力: test2
}
もっと推奨
変数の定義には const
, let
がES2015で追加されている。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements#Declarations
そちらに移行していくのがベスト。
参照
https://developer.mozilla.org/ja/docs/Glossary/Hoisting
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/var#var_hoisting