Kula.blog

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 consts:

// 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.


← Home