JavaScriptの基礎として、JavaScript独特の挙動をみていきます。
JavaScriptは他のプログラミング言語には見られない変数の巻き上げ(hoisting – ホイスティング)というものがあります。
ここを押さえておかないと、コードを実行した時に思ったように動かなかったり、その原因がわからなかったりします。
ここではこの巻き上げ(hoisting)について順に見ていきましょう。
巻き上げ(hosting)
先ほども触れましたが、JavaScriptは他のプログラミング言語には見られない変数の巻き上げ(hoisting)というものがあります。
JavaScriptでは、変数や関数の宣言をスコープ内の一番上にもってくることを巻き上げ (hoisting) といいます。
関数の巻き上げ
具体的なコードで見て行きましょう。
次のコードは2019年が変数で指定した年(誕生年)から何年経っているかという年齢計算のコードです。
function calculateAge(year) {
console.log(2019 - year);
}
calculateAge(2000); // 19
単に2019から指定の西暦を引いてるだけの関数です。実行すれば「19」になるのはわかると思います。
これを次のように書き換えてみます。
calculateAge(2000);
function calculateAge(year) {
console.log(2019 - year);
}
先ほどのコードと違い、呼び出しの関数を一番上に置いています。
この形だと他のプログラミング言語ではほぼエラーになりますが、実行するとこうなります。
このように、関数の宣言を一番上のスコープに持ってきても実行することができます。
関数の宣言では巻き上げができましたが、関数式は巻き上げされないため、次のようなコードではエラーになります。
calculateAge(2000);
var calculateAge = function(year) {
console.log(2019 - year);
};
// calculateAge(2000);
実行するとこうなります。
関数式の場合は、コメントアウトして記述しているように上側ではなく下側に記述して実行します。
変数の巻き上げ
次は変数の巻き上げを見てみましょう。
console.log(age);
var age = 23;
function foo() {
console.log(age);
var age = 30;
console.log(age);
}
foo();
console.log(age);
ここで出てくる関数foo()は適当なものです。単に変数を表示するだけの関数です。
このコードを実行するとJavaScriptコンソールには次のように表示されます。
一番上のconsole.log()は変数宣言の前なのでundefinedになっています。
関数を定義した後に、foo();で呼び出した最初のconsole.log()は、外側で定義したグローバル変数の23が出力されそうですが、そうはなりません。またエラーではなくundefinedになります。これは、関数内で宣言した変数が関数内のどこで宣言しても関数内の先頭に巻き上げられます。これで、変数の宣言のみ(数値部分は別)が巻き上げられて、var age;があるという意味合いになります。2つ目のconsole.log()は30が入って出力されています。
foo();を呼び出した後の最後のconsole.log()は、一番上で宣言した変数を出力しています。
まとめ
JavaScript独特の挙動の巻き上げ(hoisting – ホイスティング)を見てきました。
巻き上げは他のプログラミング言語には見られない動きで、ここを押さえておかないと、コードを実行した時に思ったように動かなかったり、その原因がわからなかったりします。
関数の実行は巻き上げが行われますが、関数式は同様にはできずエラーになります。
関数内での変数の宣言は、どの位置で行っても関数内の一番上で宣言した形になって値を代入しない限りundefinedとして扱われます。