What is the temporal dead zone, and which declarations does it apply to?
The temporal dead zone is the window between the moment a scope is entered and the moment a let, const or class declaration in that scope actually executes. The binding for the name exists during that window, because the engine creates all bindings up front, but it has no value yet. Reading it throws a ReferenceError.
console.log("start");
try {
console.log(later); // ReferenceError - the binding exists but is not ready
} catch (err) {
console.log("caught:", err.name); // "ReferenceError"
}
let later = "declared further down";
console.log(later);It applies to let, const and class declarations. It does not apply to var, because a var binding is given its empty value immediately, and it does not apply to function declarations, because the whole function is created up front.
What makes the dead zone confusing is that it turns an ordinary ordering mistake into a crash at runtime. The code reads as though the variable were simply not there yet, but instead of a blank value you get an exception, and the message names the variable rather than telling you it was used too early. The fix is almost always to move the declaration above its first use, or to restructure the code so the declaration runs first.
The zone also explains a confusing detail about typeof. The typeof operator is safe on a name that was never declared at all, which is the basis of feature detection. Inside the dead zone it still throws, because the binding exists and the engine refuses to read a binding that has not been initialised.