🔝
JavaScript は全ての宣言を巻き上げる
巻き上げ
JavaScript において、巻き上げ (英語: hoisting)[1] は 変数の宣言がスコープの先頭で行われたかのように扱われる動作 を指します。
// | let b |
{ // | |
// | let a |
let a = 10 // | a = 10 |
} // | |
let b = 20 // | b = 20 |
function
巻き上げ function
で宣言した関数は巻き上げによって 前方から実行できます。
// | function f () { | |
// | return "hello" | |
// | } | |
console.log(f()) // | console.log(f()) | => hello |
// | | |
function f () { // | | |
return "hello" // | | |
} // | | |
var
巻き上げ var
で宣言した変数は巻き上げによって 前方から参照できます。
ただ、巻き上げの対象となるのは宣言のみで、初期化や代入は反映されません。
var
で宣言と初期化を行った変数を前方から参照した場合、初期化時の値ではなく undefined
が取得されます。
// | var x | |
console.log(x) // | console.log(x) | => undefined |
// | | |
var x = "hello" // | x = "hello" | |
let
, const
, class
巻き上げ let
, const
, class
で宣言した変数は巻き上げによって 前方から参照できません。
let
, const
, class
で宣言した変数を前方から参照した場合、エラー[3]が発生します。
// | let x | |
console.log(x) // | console.log(x) | => ReferenceError: Cannot access 'x' before initialization |
// | | |
let x = "hello" // | x = "hello" | |
let
, const
, class
で宣言した変数は巻き上げによって前方から参照できませんが、宣言の巻き上げ自体は行われています。
よって、変数の初期化後に実行される関数内であれば 表記上での前方から初期化後の値を参照できます。
// | let x | |
const f = () => { // | | |
console.log(x) // | | |
} // | | |
// | | |
let x = 'hello' // | x = 'hello' | |
// | | |
f() // | console.log(x) | => hello |
使い道としては 相互再帰な関数の定義 や 補助関数の記述位置を下にしたい 場合が考えられそうです。
相互再帰な関数の定義
const main = () => {
// ...
sub()
}
const sub = () => {
// ...
main()
}
補助関数の記述位置を下にしたい
export const main = () => {
sub()
}
const sub = () => {
// ...
}
(まとめ) JavaScript は全ての宣言を巻き上げる
巻き上げ | 変数の宣言がスコープの先頭で行われたかのように扱われる動作 |
宣言方法 | 宣言の巻き上げ | 定義の巻き上げ |
---|---|---|
function |
○ | ○ |
var |
○ | △ |
let , const , class
|
○ | × |
Discussion