Learn JS. Hoisting (2). Temporal Dead Zone
In my previous post Learn JS. Hoisting (1), I've explained how Lexical Environment is responsible for what most people call hoisting. Hoisting is not a term from the specification but is a label for how Lexical Environment works in JavaScript. The same will be true for the Temporal Dead Zone.
Let's start with an example.
console.log(bar); // undefined
console.log(foo); // throws ReferenceError
var bar = 1;
let foo = 2;
Let's figure it out step by step, looking at how Lexical Environment looks like before execution.
LexicalEnvironment = {
bar: undefined
foo: < uninitialized > // throw ReferenceError if anyone tries to access it
}
var
, let
and const
declarations are hoisted. The only difference is what happens when you try to access the variable before the declaration.
Let's take a look at specification:
The variables are created when their containing Lexical Environment is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated.
from: http://ecma-international.org/ecma-262/#sec-let-and-const-declarations
Let me show you an example with LexicalBinding:
// LexicalEnvironment = { foo: < uninitialized > - throw Reference Error }
let foo = 2; // LexicalBinding!
// LexicalEnvironment = { foo: 2 }
Just for completeness the same is true for const
s:
// LexicalEnvironment = { FOO: < uninitialized > - throw Reference Error }
const FOO = 2; // LexicalBinding!
// LexicalEnvironment = { FOO: 2 }
Temporal Dead Zone #
Every line of code when the value in Lexical Environment is equal to <uninitialized>
is commonly called Temporal Dead Zone as you can't use identifiers (names) of your const
or let
variables before their declarations.
// LexicalEnvironment = { FOO: < uninitialized > - throw Reference Error }
// Temporal Dead Zone: Start
const FOO = 2; // LexicalBinding!
// Temporal Dead Zone: END
// LexicalEnvironment = { FOO: 2 }
What if there is no initial value? #
Let's say that you declare your let
variable but you calculate it's value later. What will happen to Temporal Dead Zone? Will there be LexicalBinding?
// LexicalEnvironment = { bar: < uninitialized > - throw Reference Error }
// Temporal Dead Zone: Start
let bar; // LexicalBinding!
// Temporal Dead Zone: END
// LexicalEnvironment = { bar: undefined }
console.log(bar); // undefined
bar = "some value"
// LexicalEnvironment = { bar: "some value" }
Both let and const get undefined
as a value until you assign one. Of course, after the LexicalBinding.
Want to learn more?
Sign up to get a digest of my articles and interesting links via email every month.