JavaScript - 関数の巻き上げ
はじめに
次にようなコードを書いていてエラーが起きたので、今回は関数の巻き上げについてメモ。
func(); //=> Hello function
funcExpression(); //=> Uncaught ReferenceError: Cannot access 'funcExpression' before initialization
function func () {
console.log('Hello function');
}
const funcExpression = function () {
console.log('Hello function expression');
}
巻き上げとは?
巻き上げとは、Hoistingとも言われECMAScript2015 (ES6)から導入された仕様です。MDNの説明では、
例えば、巻き上げでは変数と関数定義は物理的にコードの一番上に移動すると厳密に定義されています、これは実際に起こっていません。その代わりに、変数と関数宣言は compile フェーズでメモリーに配置されますが、コーディングでタイプされた場所は変わりません。
JavaScript では定義のみが巻き上げられ、初期化はそうでありません。変数が使用された後に定義や初期化された場合、値は undefined になります。
とのことです。変数定義と関数定義は、定義した行より前で呼び出し可能で、初期化は不可ということですね。
なので、上のコードは、
- 関数宣言で定義されたfunc()は、定義された行より前で呼び出し可能
- 関数式で定義されたfuncExpression()は不可
となります。
実際のコードで確認します。
巻き上げが起こる場合
巻き上げが起こるのは、関数宣言で定義された関数です。
関数宣言とはこんなやつ。
function func () {
console.log('Hello function');
}
関数宣言での関数は、レンダリング(解析)が終わった瞬間に生成されるので、宣言される前から実行することができます。
func(); //=> Hello function
function func () {
console.log('Hello function');
}
巻き上げが起きない場合
巻き上げが起こらないのは、関数式で定義された関数です。関数式とは、式の中で定義される関数のこと。
関数式とはこんなやつ。
const funcExpression = function () {
console.log('Hello function expression');
}
関数式での関数定義は、代入処理が行われたときに初めて定義されるので、巻き上げ処理は行われません。
funcExpression(); //=> Uncaught ReferenceError: Cannot access 'funcExpression' before initialization
const funcExpression = function () {
console.log('Hello function expression');
}
今回は以上にです。ご覧いただきありがとうございます。