巻き上げにおける注意点 | スコープとクロージャ | JavaScript 超完全入門 基本から発展までのすべて

スポンサーリンク
スポンサーリンク
amazon
スマイルSALE
--:--:--
ad. 価格範囲を指定して商品を探せます

巻き上げ(ホイスティング)とは?

 

ホイスティング(Hoisting:巻き上げ)とは、JavaScriptで変数や関数の宣言が、そのスコープの先頭で宣言されたように扱われる仕組みです。

ただし、「コードそのものが移動する」わけではありません。JavaScriptエンジンが実行前に宣言を処理するため、このような挙動になります。

ホイスティングを理解していないと、undefinedになったり、ReferenceErrorが発生したりする原因になります。

varのホイスティング

varで宣言した変数は、宣言だけが巻き上げられます。

console.log(a); // undefined

var a = 10;

console.log(a); // 10

実際には次のように解釈されます。

var a;

console.log(a);

a = 10;

console.log(a);

宣言だけが先に処理され、代入は元の位置で実行されます。

let・constのホイスティング

letconstもホイスティングされますが、初期化されるまではアクセスできません。

console.log(count);

let count = 10;

実行すると次のエラーになります。

ReferenceError: Cannot access 'count' before initialization

これはTemporal Dead Zone(TDZ:一時的デッドゾーン)と呼ばれる仕組みによるものです。

Temporal Dead Zone(TDZ)とは?

TDZとは、letconstが宣言されてから初期化されるまでの間を指します。

この期間は変数自体は存在していますが、アクセスするとエラーになります。

{
    // TDZ

    let value = 100;

    console.log(value);
}

TDZのおかげで、初期化前の変数を誤って使用するバグを防ぐことができます。

関数宣言のホイスティング

関数宣言は、関数全体が巻き上げられます。

sayHello();

function sayHello() {
    console.log("Hello");
}

このコードは正常に動作します。

関数全体が先に登録されるため、宣言より前でも呼び出すことができます。

関数式のホイスティング

関数式は変数として扱われます。

varで宣言した場合は変数だけがホイスティングされるため、関数はまだ代入されていません。

console.log(sayHi);

sayHi();

var sayHi = function () {
    console.log("Hi");
};

このコードでは、sayHiundefinedなので、関数として呼び出せずTypeErrorになります。

letconstの場合はTDZのため、さらにReferenceErrorになります。

関数宣言と関数式の違い

項目 関数宣言 関数式
ホイスティング 関数全体 変数のみ
宣言前に呼び出し 可能 不可
let・constとの相性 問題なし TDZの影響を受ける

var・let・constの違い

宣言方法 ホイスティング 宣言前のアクセス
var あり undefined
let あり ReferenceError
const あり ReferenceError

ホイスティングによるバグを防ぐ方法

  • varではなくletconstを使用する。
  • 変数は使用する前に宣言・初期化する。
  • 関数式は定義した後で呼び出す。
  • コードを上から順番に読めるように記述する。

まとめ

  • ホイスティングとは、宣言がスコープの先頭で処理される仕組みである。
  • varは宣言だけが巻き上げられ、初期値はundefinedになる。
  • letconstはTDZにより初期化前はアクセスできない。
  • 関数宣言は宣言前でも呼び出せる。
  • 関数式は宣言後でなければ呼び出せない。
  • 現在のJavaScriptではletconstを使用することが推奨される。