The Mysterious Temporal Dead Zone!

One of my friends had a question on my last article, “It’s not hosting, It’s hoisting”, whether, a variable declared with let is actually “hoisted”, or not. The initial reading gave us the answer of “It is hoisted”, but can’t be accessed. I was very confused. Further reading and research gave a lot of insights. If I take a pause here, return back to using var, and see this example:

console.log(count);
var count;

Console prints undefined, which is very valid, given the concept of variables declared with var getting hoisted.

Now, let’s take a step ahead, and do the same thing with let:

console.log(count);
let count;

We get the error, Uncaught ReferenceError: count is not defined(…) at console.log(count). Does it mean it is not hoisted? No, this is actually hoisted, but can’t be referenced till it is evaluated. This mystery has the name of Temporal Dead Zone.

function countMethod(){
console.log(count); //reference error
};

countMethod();
let count;

Here, we see that when countMethod() is actually called, count still hasn’t been declared, hence the reference error.

let count = 100;
console.log(count); //prints 100

(
function(){
console.log(count);//reference error
let count = 100;
})();

So, what is this Temporal Dead Zone?

Temporal Dead Zone is the state when a variable declared by let/const entering its scope, can’t be accessed until execution reaches the declaration.

According to the book ExploringJS by Dr. Axel Rauschmayer, the life cycle of a variable defined with let is defined as:

– When the scope (its surrounding block) of a let variable is entered, storage space (a so-called binding) is created for it. The variable remains uninitialized.
– Getting or setting an uninitialized variable causes a ReferenceError.
– When the execution within the scope reaches the declaration, the variable is set to the value specified by the initializer (an assignment) – if there is one. If there isn’t then the value of the variable is set to undefined.

const variables work similarly to let variables, but they must have an initializer (i.e., be set to a value immediately) and can’t be changed.

What is the need of Temporal dead zone?

Dr. Axel Rauschmater says:

To catch programming errors: Being able to access a variable before its declaration is strange. If you do so, it is normally by accident and you should be warned about it.
For const: Making const work properly is difficult. Quoting Allen Wirfs-Brock: “TDZs … provide a rational semantics for const. There was significant technical discussion of that topic and TDZs emerged as the best solution.” let also has a temporal dead zone so that switching between let and const doesn’t change behaviour in unexpected ways.
Future-proofing for guards: JavaScript may eventually have guards, a mechanism for enforcing at runtime that a variable has the correct value (think runtime type check). If the value of a variable is undefined before its declaration then that value may be in conflict with the guarantee given by its guard.

Now, while we know why TDZ was introduced, let’s take a look of one more case where TDZ is influencing results. This is with default parameters, which ES6 has introduced.

This example shows how default parameters work in ES6:

function getAddedValue(firstArgument,secondArgument, thirdArgument=3) {
console.log(firstArgument+secondArgument+thirdArgument);

}

getAddedValue(1,2); // 6

Now, in this case, we see TDZ kicking in:

function getAddedValue(firstArgument=secondArgument,secondArgument) {
console.log(firstArgument+secondArgument);
}

getAddedValue(undefined,1); //reference error

getAddedValue(undefined,1) throws an error because secondArgument is defined after firstArgument and is therefore unavailable as a default value.

While understanding all this, getting confused, and experimenting, there were two side learnings as well:

1. In babel.js transpiler, TDZ is not enabled by default. Turn on “high compliance” mode to use it in the REPL. Supply the es6.spec.blockScoping flag to use it with the CLI or as a library. (http://stackoverflow.com/questions/33198849/what-is-the-temporal-dead-zone)

2. Firefox 43 version doesn’t support features of let and TDZ in ES6. Check this link for ES6 feature compatibility: https://kangax.github.io/compat-table/es6/

Overall, although TDZ might seem to be confusing, it can help us track errors and prevent unwanted bugs.

For examples, please refer to https://github.com/usrlocalts/temporaldeadzone

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s