はじめに

javascrptの重要な概念の一つ,「変数の巻き上げ(hoisting)」についてのまとめ。
javascrpt特有で最重要ポイントの一つ。
これを分かってると,コードの読み方が一歩プロに近づく…カモ

目次

  1. はじめに
  2. 大前提1 グローバル変数とローカル変数
  3. 本題1 変数の巻き上げ
  4. 本題2 巻き上げの正体
  5. 参考

大前提1 グローバル変数とローカル変数

まずは,基礎中の基礎,「グローバル変数」と「ローカル変数」について。

変数
  • js
1
2
3
4
5
6
7
8
9
10
var shaver = '松本イズミ';
function show(){
console.log(shaver);
var imo = '松本いずみ';
console.log(imo);
}

show();
console.log(shaver);
console.log(imo);

これを実行すると

1
2
3
4
松本イズミ
松本いずみ
松本イズミ
Uncaught ReferenceError: imo is not defined

と表示されます。
最後が「imo is not defined」となってます。
これは,変数imoこと「松本いずみ」はローカル変数だから。
つまり,変数imoは関数show()の中でしか使えないということ。
逆に,変数shaverこと「松本イズミ」はグローバル変数なので,関数show内でも外でも使えます。当然,新しく作った関数内でも使えます。

本題1 変数の巻き上げ

さて,ここからが本題です。
まずは,コードを見てみます。

hoisting
  • js
1
2
3
4
5
6
7
var izumi = '松本イズミ';
function show(){
cosole.log(izumi);
var izumi = '松本いずみ';
console.log(izumi);
}
show();

コンソールにどのように表示されるでしょうか?

1
2
松本イズミ
松本いずみ

と思った人は不正解。
正解は

1
2
undefined
松本いずみ

本題2 巻き上げの正体

Javascrptでは,関数内のどこでもvar宣言で変数を定義できる。
しかし,実行時にはその変数は関数の先頭で宣言されたものと同じ扱いになる。
つまり,以下のコードと同等となる。

hoisting
  • js
1
2
3
4
5
6
7
8
var izumi = '松本イズミ';
function show(){
var izumi; //undefined
cosole.log(izumi);
var izumi = '松本いずみ';
cosole.log(izumi); //松本いずみ
}
show();

グローバル変数のでて定義した「松本イズミ」は,関数内で巻き上げられた[var izumi;]に上書きされちゃうんですね。
結果,表示されるのは「undefined」になると。
なぜ,このような仕様になってるのかというと,結構複雑な事情があるみたい。
次回,さらに掘り下げてみます。

参考

知らないと怖い「変数の巻き上げ」とは?
やっとわかったjsの「巻き上げ」