🎄

ENCA 7日目: Temporal Dead Zone (TDZ) をやめたい(未定)

2024/12/07に公開

varlet/const の違い

ES2015 から変数宣言に let/const が導入されました。レガシーな var と比べてブロックスコープであり、同一スコープでの再宣言ができないようになっています。

また let/const には変数の初期化(宣言)前にアクセスすると ReferenceError を投げる仕様があります。これを Temporal Dead Zone (TDZ) と呼びます。

console.log(foo); // undefined
var foo = "foo";
console.log(foo); // throws ReferenceError
let foo = "foo";

これら仕様によってバグの発生を抑制してくれています。

TDZ によるパフォーマンスの問題

TDZ は実行順(時間)に依存していることから Temporal という形容詞が使われています。例えば以下のコードは問題なく実行できます。

function showFoo() {
  console.log(foo); // "foo"
}

const foo = "foo";
showFoo();

つまり TDZ に引っかかるかどうかを静的解析することは困難であり、基本的に実行時チェックされています。よって var よりも多少パフォーマンスが悪くなってしまいます。これは通常問題にならないため積極的に let/const を採用したほうが良いですが、スコープが大きい場合は無視できない場合があります。

実際に TypeScript の公式コンパイラである tsc において、行数が4桁オーダーの大きい函数内でのみ、あえて var が使われています。

https://github.com/microsoft/TypeScript/issues/52924

これについては mozaic.fm で JavaScriptCore を実装されている Constellation さんの話が参考になるかと思います(ES2015 を実装していた時の話であることに留意してください)。

https://mozaic.fm/episodes/19/es7.html

TDZ をやめたい

2023年9月の会議で TDZ が効果的かどうか議論されました。

https://github.com/tc39/notes/blob/main/meetings/2023-09/september-27.md#tdz-what-is-it-good-for

Babel や TypeScript で ES5 ターゲットに出力するときに var に変換されますが、TDZ を無視した変換となっています[1]。つまりこの機能を取り除いて、初期化前にアクセスした際には単に undefined としてしまっても、Web ディベロッパー的に問題ないと思われます。

この議論は将来また提案として進めるかもしれないという扱いになっています。

脚注
  1. Babel はオプションで TDZ が有効にできるようです。 ↩︎

Discussion