What is the 'Temporal Dead Zone' in JavaScript?
Tags: javascript, es6, webdev
Published: 2019-11-29 19:24:28

This concept is probably not something that you come across too often and sounds a little bit weird. But it can be useful to know some details to avoid possible bugs or problems in your code.

So, let's look at the example below. It's easy to see that it will print `foo` to console.
```javascript
var foo = 'foo';
console.log(foo); // foo
```
<br />
What if we change the order of the lines as below:

```javascript
console.log(foo);
var foo = 'foo';
```

Now you will see that it prints `undefined`. This is because the `var` declaration is hoisted but the value of variable is undefined when console.log line is executed.

Now let's add a bit of ES6 to our simple example.

```javascript
console.log(foo);
let foo = 'foo';
```

If you run this code on your console, you will get a `ReferenceError`. This is one of the main differences between `var` and `let`/`const`. When `let`/`const` variables are accessed before their declaration, they throw a ReferenceError instead of having undefined value.

You may think that `let`/`const` variables are not hoisted and we're getting ReferenceError because of this, but this is not correct.

Let's explain that in a little bit more complex example.

```javascript
var foo = 'first';
function example() {
  console.log(foo);
  var foo = 'second';
}
example();
```

What do you think the code above will print to console?

The answer is `undefined`. This is a simple example that explains how hoisting works in JavaScript. `foo` variable is hoisted inside of the function scope but it's not initialized where the console.log line is executed, so it prints `undefined`. This is the expected result.

So what if we change it as below?

```javascript
let foo = 'first';
function example() {
  console.log(foo);
  let foo = 'second';
}
example();
```

This code above will throw a `ReferenceError` similar to the `let` example before. This is because `let`/`const` variables are actually hoisted, but they throw `ReferenceError` if they're accessed before being initialized. The variable is in a "temporal dead zone" from the start of the block until the initialization is processed.

If you want to dig deeper you can see MDN documentation of `let` [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone), and ES specification [here](https://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations).

There is a misconception that says let/const are not hoisted in JavaScript, we cannot say that is correct. According to [ES6 specification](https://www.ecma-international.org/ecma-262/9.0/index.html#sec-let-and-const-declarations): <em>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.</em>

Note: You can see another great explanation of hoisting of let/const [here](https://stackoverflow.com/questions/31219420/are-variables-declared-with-let-or-const-not-hoisted-in-es6/31222689#31222689).

-----
You can also read this post in [my blog](https://blog.ahmetkapusuz.com/what-is-the-temporal-dead-zone-in-javascript/).