JavaScriptにおける巻き上げ
JavaScriptの巻き上げ(Hoisting)を正確に把握してなかった為に、挙動に困った事があったので、学習用にまとめました。
巻き上げとは
巻き上げ(Hoisting)とは、変数宣言や関数宣言がスコープの最上部に移動する挙動。
以下コードは関数宣言のhogeFunction
が巻き上げられ、スコープの最上部に移動した結果、1行目でhogeFunction()
を呼び出すことができています。
console.log(hogeFunction()); // "こんにちわ"
function hogeFunction() {
return "こんにちわ";
}
これが基本的な巻き上げです。
ただ、それぞれ注意すべき挙動の違いがあるので見ていきます。
変数の巻き上げ
var
で宣言された変数は、そのスコープの最上部に巻き上げられます。
ただ、以下のコードでは最初のconsole.log
はundefined
を出力しています。
基本的に宣言のみ巻き上げされて、初期化や代入は巻き上げされません。
つまり以下コードでは、var hoge;
という宣言のみが巻き上げられ、hoge = 1
という代入は巻き上げされません。
なので、最初のconsole.log
では宣言はされているものの未定義のままです。
console.log(hoge); // undefined
var hoge = 1;
console.log(hoge); // 1
varとlet/constの挙動
var
は巻き上げられます。
let
とconst
は巻き上げられません。
let
とconst
も内部的には巻き上げられますが、宣言される行まで一時的なデッドゾーンにあります。この間、変数は存在するもののアクセスできないため、参照エラーになります。
console.log(hoge); // ReferenceError: hoge is not defined
let hoge = 1;
console.log(hoge); // 1
関数の巻き上げ
関数の巻き上げは、関数宣言と関数式で挙動が異なります。
関数宣言
関数宣言は、コードの最上部に巻き上げられます。
console.log(hogeFunction()); // "こんにちわ"
function hogeFunction() {
return "こんにちわ";
}
関数式
関数式は変数に関数を割り当てて定義するため、変数の巻き上げの規則に従います。
var
で宣言された場合、変数名は巻き上げられますが、関数の本体は巻き上げられません。
※関数式でもlet
やconst
の宣言は巻き上げられない為、変数宣言前にアクセスしようとするとエラーが発生します。
console.log(hogeFunction); // undefined
var hogeFunction = function() {
return "こんにちわ";
};
console.log(hogeFunction()); // "こんにちわ"
参考
Discussion