The temporal dead zone (TDZ) is the span of time from entering a scope until a let, const, or class declaration in it is evaluated. During that span the binding exists but is uninitialized. Any read or write of it throws a ReferenceError; the spec's GetBindingValue and SetMutableBinding on a Declarative Environment Record check for this.
Key points:
- "Temporal", not "textual". The zone is about when code runs. A function defined above a
letcan read it safely, as long as it is called after theletline has run. - It proves the binding was hoisted. An inner
let xmakes an earlier read ofxin the same block throw, instead of falling through to an outerx. typeofis not safe.typeof undeclaredreturns"undefined"because the name is unresolvable.typeof tdzNamethrows, because the name resolves to an uninitialized binding.- Applies to
classand parameters too.classdeclarations behave likelet, and parameters are initialized left to right, so a default can't use a later parameter. - Why it exists. It turns a use-before-define bug into a loud error, and it makes
constcoherent: a constant can't be observed holdingundefinedfirst.
The zone ends when the declaration is evaluated. let x; with no initializer then sets x to undefined. The V8 message is "Cannot access 'x' before initialization"; the text is engine-specific, but the error type is not.