この記事は、岩手県立大学 Advent Calendar 2019 9日目の記事です。
1. はじめに
こんにちは。岩手大学のTakuyaHanadaです。
今回は、初Advent Calendarということで(関係はないです)、JavaScriptの巻き上げについてアウトプットしていきます!
間違い等あれば、教えてくださると勉強になります。
2. 巻き上げとは
-
var
を使って宣言された変数 -
function
を使って宣言された関数
が、現在のスコープで宣言前でも使えること。
3. よくわかんないから実際のコードを見て学ぶ
以下のサンプルコードの出力を予想しながら見てみてください!
※ 出力結果はnodeで動作させた場合のものです。
3-1. サンプルコード1
var hoge = 'おはよう靴下';
console.log(hoge);
おはよう靴下
これは当たり前ですね。
var hoge = 'おはよう靴下';
console.log(hoge);
3-2. サンプルコード2
console.log(hoge);
var hoge = 'おはよう靴下';
undefined
巻き上げが起こります。
はい?と思うかもしれません。これが巻き上げです。
巻き上げが起こり、var hoge
が一番上(正確に言うと、宣言されたスコープの一番上)に来ています。
var hoge; // 巻き上げが起こっている
console.log(hoge);
hoge = 'おはよう靴下';
3-3. サンプルコード3
console.log(fuga);
let fuga = 'おはよう靴下';
ReferenceError: Cannot access 'fuga' before initialization
巻き上げは起こりません。
ん?と思うかもしれません。
しかし、巻き上げが起こるのはvar
で宣言した場合のみです。
なので、この場合はコードの通りに動きます。(const
の場合もlet
と同様です)
console.log(fuga);
let fuga = 'おはよう靴下'; // let で定義しているため、巻き上げが起こらない
3-4. サンプルコード4
if (hoge !== 'おはよう') {
var fuga = '靴下';
if (fuga === '靴下') {
var hoge = 'おはよう';
}
}
if (hoge === 'おはよう') {
console.log(hoge + fuga);
}
おはよう靴下
巻き上げが起こります。
これは、サンプルコード2と同様です。
巻き上げが起こり、var hoge
とvar fuga
が一番上に来ています。
var hoge; // 巻き上げが起こっている
var fuga; // 巻き上げが起こっている
if (hoge !== 'おはよう') {
fuga = '靴下';
if (fuga === '靴下') {
hoge = 'おはよう';
}
}
if (hoge === 'おはよう') {
console.log(hoge + fuga);
}
3-5. サンプルコード5
function fn() {
console.log('fnの中のhoge', hoge);
var hoge = 'おはよう靴下';
}
fn();
console.log('fnの外のhoge', hoge);
fnの中のhoge undefined
ReferenceError: hoge is not defined
巻き上げが起こります。
このサンプルコードは、混乱するかもしれません。
しかし、巻き上げは
var
を使って宣言された変数が、現在のスコープで宣言前でも使えること。
なので、現在のスコープ(サンプルコード5の場合はfn
)でしか使うことができません。
つまり、以下のように動いています。
function fn() {
var hoge; // 巻き上げが起こっている
console.log('fnの中のhoge', hoge);
hoge = 'おはよう靴下';
}
fn();
console.log('fnの外のhoge', hoge);
3-6. サンプルコード6
fn();
function fn() {
console.log('おはよう靴下');
}
おはよう靴下
巻き上げが起こります。
これは関数の巻き上げです。関数もvar
と同様に巻き上げが起こります。
function fn() { // 巻き上げが起こっている
console.log('おはよう靴下');
}
fn();
3-7. サンプルコード7
fn();
const fn = () => {
console.log('おはよう靴下');
};
ReferenceError: Cannot access 'fn' before initialization
巻き上げは起こりません。
これはサンプルコード3と同様です。
const
でfn
という変数を定義しているため、このようになります。
fn();
const fn = () => { // 巻き上げは起こらない
console.log('おはよう靴下');
};
3-8. サンプルコード8
fn();
var fn = () => {
console.log('おはよう靴下');
};
TypeError: fn is not a function
巻き上げが起こります。
これは、サンプルコード7と同様にfn
という変数を定義していますが、var
を使っているため、巻き上げが起こります。
var fn; // 巻き上げが起こっている
fn();
fn = () => {
console.log('おはよう靴下');
};
4. おわりに
以上がJavaScriptの巻き上げでした。
var
, function
を使う際には気をつけましょう。