はじめに
初学者です。
ホイスティングについて学んだので備忘録を残します。
ホイスティングってなに?
コンテキスト内で宣言した変数や関数の定義をコード実行前にメモリに配置すること
宣言の巻き上げともよばれる
宣言した関数よりも前でその関数を呼び出しても実行できますよね。
それです
いろんなケースのコードを見ていこう
関数
a();
function a() {
console.log('a is called')
//関数の定義が実行より後でもホイスティングによって実行可能になる
}
var
console.log(b); //処理結果 undefined
var b = 0; //
// この場合のホイスティングは
//変数bのメモリースペースを確保し値に特殊な値(undefined)を設定
let・const
console.log(b); //処理結果 エラー
let b = 0; //
//letやconstはホイスティングで初期化(undefined)されない
//挙動が違うためvarの使用は非推奨である
ここで一度整理したい
ホイスティングが行われることによって関数宣言よりも前で宣言した関数を呼び出しても使える
これはJavaScriptエンジンがコンテキストを生成した際に変数や関数を発見しコード実行前にメモリに配置するからである。
変数(定数)の定義にはvar/let/constがあるが、varとlet+constの挙動には違いがある。
変数宣言よりも前でその変数を参照した場合
varの場合は変数をメモリに配置し、値にundefinedを代入する挙動
let+constの場合はホイスティングが行われずにエラーになる(厳密には行われているらしいがエラーがでる)
このようにvarとlet+constには挙動の違いがある。これはホイスティングだけではなく、ブロックスコープの生成の有無など
その他の面でも挙動に違いがある。これらを理由に現在varを使うのは非推奨である
ホイスティングが発生するタイミングはコンテキストが生成される瞬間
function a() {
console.log(z)
let z = 1;
}
//関数aの中身は記述の順番が間違っているが、呼び出していないため
//関数aのコンテキストは生成されていない
//関数aのコンテキストが生成された瞬間ホイスティングが発生しエラー
//になる(関数aを呼び出すとエラー)
関数式
a();
const a = function() {
let c = 1;
console.log(c)
}
//処理結果:エラー
//関数式は変数の宣言と同じ挙動をするため関数宣言と異なり
//宣言より前で呼び出すとエラーになる
コンテキストが生成されるたびにホイスティングが発生し宣言部がメモリースペースに配置される
まとめ
コンテキストが生成された瞬間にホイスティングが発生する
ホイスティングによって関数や変数がコード実行前にメモリに保存される
メモリに保存してからコードを実行するため関数はどこからでも呼び出すことができる
ホイスティングの発生はコンテキストが生成されたタイミングなので、関数スコープ内で記述が間違っていても
呼び出していなければホイスティングは行われない。