0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TDZによるエラー【JS】

Posted at

はじめに

未知の仕様がありましたので共有です。

const f = () => console.log(x)
const x = 'xx'

f()

このコードを実行すると、const x ...つまり、xxと表示されます。
const fの定義時点ではxが何者か定義されていませんが、これでも動くんですね。
これはこれで、エラーにしてもいいのでは・・・?

では、これではどうでしょう?

const f = () => console.log(x)
- const x = 'xx'

f()
+ const x = 'xx'

const xf()の実行時に定義されていません。
エラーが発生するでしょう。
ReferenceError: x is not definedxが定義されてないよ)と表示されるはずです。

答え
ReferenceError: Cannot access 'x' before initialization

あれ?
予想は「xが定義されてないよ」でしたが、
実際は「xが初期化する前にアクセスすることはできないよ」でした。

試しに、const xを消してみましょう。
これこそ、ReferenceError: x is not definedxが定義されてないよ)が表示されるはずです。

const f = () => console.log(x)

f()
- const x = 'xx'
ReferenceError: x is not defined

予想通りですね。

ではやはり、最初のエラーは「xが定義されていない」とは別のエラーのようです。

TDZの影響

let または const 変数は、ブロックの始まりからコードが実行されて変数が宣言され初期化される行に到達するまでは、「一時的なデッドゾーン」(TDZ) 内にあると言います。

人によっては let, const, class を巻き上げが行われないと見なしますが、それは一時的デッドゾーンで宣言前に変数を使用することを厳しく禁止しているからです。

なるほど。どうやら一時的デッドゾーン(TDZ)というものが存在するようです。

直接、件のコードに対する言及ではありませんが、以下の記述がありました。

 const 宣言が定義されているスコープ全体をまだ「汚染」しているため、 console.log(x) 文はまだ初期化されていない const x = 2 宣言から x を読み込み、 ReferenceError を発生します。

という説明がありました。「汚染」いいですね。

  1. 初期化(宣言)の行われたスコープはTDZにより、ある種「汚染」される
  2. その中での呼出はReferenceError: Cannot access 'x' before initializationを発生させる
  3. 事前に宣言されていても、TDZによるエラーが優先される

他の実例

これはどうでしょう?
f()console.log(x)の2箇所でxの出力を試みています。

const f = () => {const x = 'xxx'; console.log(x) }

f()
console.log(x)
const x = 'xx'

一見、どちらもconst x = 'xx'の影響でエラーになりそうですが・・・

xxx
/home/runner/testtdz/tdz.js:3
console.log(x)
            ^

ReferenceError: Cannot access 'x' before initialization

xxxが出力されているので、最初のf()は予想に反して動いていますね。
console.log(x)は予想通りのエラーです。

なぜ、f()はエラーにならないのでしょう?

答え

スコープが違うから

f()は、関数内で宣言されたconst x = 'xxx'を優先します。関数内にxが存在する以上、これ以外のxを認識しません。
よって、TDZによる「汚染」は起きていないということですね。

なので、例えば以下の例ではReferenceError: Cannot access 'x' before initializationになります。

const f = () => { console.log(x); const x = 'xxx' }
f();

おわりに

知らない挙動がまだまだありますね。

さて、次は何を書こうかしら・・・

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?