質問: 'hello' console.log(str) } show() /* 出力 console.log(str) ^ ReferenceError: str is not defined */ ``` --- `let`と`const`にも`var`と同様に巻き上げが起こるのであれば、上記3つの出力結果はいずれも ``` undefined hello ``` になると思います。 実行環境は`VSCode`です。 もしかしたら巻き上げを誤解している気がしたので質問させていただきました。 よろしくお願いします。
回答: `let`や`const`でもある意味では巻き上げは発生します。下記のNOTEに詳しく書いています。 13.3.1 Let and Const Declarations - ECMAScript® 2018 Language Specification しかし、`var`や関数宣言とは巻き上げ時の動作が異なります。 巻き上げと言ったとき、大きく二つの動作が行われます。 1. 環境レコード生成時にその環境レコード内に変数も作成すること。 2. 変数を作成する時に何らかの値(`undefined`や関数そのもの等)を代入(assigne)すること。 `var`、関数宣言、関数の仮引数は1.と2.の両方の動作を行いますが、`let`や`const`は1.の動作のみを行い、変数を「何も代入されていない状態」にします。この「何も代入されていない状態」は`undefined`が代入された状態とは異なる状態です。そして、「何も代入されていない状態」の変数を参照すると、ReferenceErrorが発生するようになっています。 つまり、1.の意味での巻き上げは`let`や`const`でも発生するのですが、1.と2.の両方の意味での巻き上げは発生しないと言うことです。 本当に一切の巻き上げが発生しないのは非strictモードでの`var`等を使用しない代入です。この場合は、グローバル環境レコード(グローバルオブジェクトと同一)にグローバル変数(グローバルオブジェクトのプロパティ)が作られますが、巻き上げが起きるわけでは無くて、まさしく、代入時にグローバル変数(グローバルオブジェクトのプロパティ)が作られます。