DEV Community

Cover image for Temporal Dead Zone in JavaScript Explained (TDZ)
Alex Devero
Alex Devero

Posted on • Originally published at blog.alexdevero.com

Temporal Dead Zone in JavaScript Explained (TDZ)

Temporal dead zone in JavaScript (TDZ) is one of the topics every JavaScript developer should know. This tutorial will teach you all you need to know about it. You will learn what temporal dead zone in JavaScript is and how it works. You will also learn about scope and variable declaration and initialization.

Note to the reader: if you already understand variables, scope and variable declaration and initialization, you can skip the beginning and scroll to the last section.

Three types of variables

In the beginning, there was only one type of variables in JavaScript. When you wanted to declare a new variable you had to use the var keyword. This changed when ECMAScript 6 specification was released. One change that was introduced by this specification were two new types of variables.

These new two types of variables were let and const. There are differences between them, the var, let and const. Some of these differences are more important and some less. Among these differences are two that are important to understand how temporal dead zone in JavaScript works. Also how it works with each type.

// Declare variable with var keyword
var myVariableVar = 'Lex'

// Declare variable with let keyword
let myVariableLet = 47

// Declare variable with const keyword
const myVariableConst = ['DC']
Enter fullscreen mode Exit fullscreen mode

Three types of scopes

The first important difference is how these variables work with scope. In JavaScript, there are two, well, three, types of scope, global, local or function and block. Global scope is a scope outside any function or code block. Local or function scope is a scope inside functions. When you create a function you also create a local scope.

Variables declared in a global scope are visible and accessible everywhere. Variables you declare in a local scope are accessible and visible only inside that scope, not outside it. The third scope, block, is created by using a pair of curly brackets. For example, when you use [if...else statement], some loop and so on, you are also creating block scope.

// Variable in a global scope
let myGlobalVariable = 'Global'

// Variable in a local (function) scope
function myFunc() {
  // This is new local scope
  // created for this function
  let myLocalVariable = 'Local'
}

// Variable in a block scope
if (true) {
  // New block scope is created inside the curly brackets
  let myBlockVariable = 'Block'
}
Enter fullscreen mode Exit fullscreen mode

Scope and var

Important thing about var variable is that it cares only about the first two: global and local scope. It doesn't care about the third: block scope. Let's say you declared a variable using var in the global scope. Then, you created a block scope with if...else statement. Inside it you declared another var variable.

This new variable has the same name as the global var. Since var doesn't care about block scope the var inside the if...else will overwrite the global var.

// Declare variable with var
var myVariableVar = 'Lex'

// Create block scope with if...else statement
if (true) {
  // Declare new variable with var,
  // but use the same name as for the first var
  var myVariableVar = 'Alexander'
}

// Log the value of myVariableVar
console.log(myVariableVar)
// Output:
// 'Alexander'
Enter fullscreen mode Exit fullscreen mode

Scope and let (and const)

The above will not happen if you declare those variables with let. The let variable knows and respects block scope. By using the if...else statement you create new block scope. This scope limits the visibility and accessibility of the new let variable. JavaScript "sees" these two let as two different variables.

// Declare variable with let
let myVariableLet = 'Lex'

// Create block scope with if...else statement
if (true) {
  // Declare new variable with let,
  // but use the same name as for the first let
  let myVariableLet = 'Alexander'
}

// Log the value of myVariableLet
console.log(myVariableLet)
// Output:
// 'Lex'
Enter fullscreen mode Exit fullscreen mode

The const variable works in the same way as let. It also respects block scope. So, block-scoped const will not collide with global const, or the other way around.

// Declare variable with const
const myVariableConst = 'Lex'

// Create block scope with if...else statement
if (true) {
  // Declare new variable with const,
  // but use the same name as for the first const
  const myVariableConst = 'Alexander'
}

// Log the value of myVariableConst
console.log(myVariableConst)
// Output:
// 'Lex'
Enter fullscreen mode Exit fullscreen mode

Variable declaration and initialization

When you create a new variable, there are two steps that happen. The first step is about declaring the variable. This means that JavaScript creates an identifier for the name of the variable you just created and reserves memory for it. The second step is about initializing the variable.

Variable initialization means assigning a value to the variable. This might happen right away during declaration if you create a variable and assign it a value. Or, it will happen later, when you assign that variable some value. It might also never happen of you don't assign that variable any value.

// Declare variable
var myVariableVar
let myVariableLet

// Initialize variable
myVariableVar = 'Dex'
myVariableLet = 33

// Declare and initialize variable
let myVariableLetTwo = 'Let\'s do it all at once.'
Enter fullscreen mode Exit fullscreen mode

Declaration and initialization differences between var, let and const

What you need to know is that for this process is a bit different for some types of variables. The first step is the same. What differs is the second step. When you declare a variable with var without initializing it will be initialized anyway. Variables you declare with var will have the default value of undefined.

The undefined is also what you get if you try to access the value of declared, but not initialized var variable. Variables you declare with let and const work differently. They don't have any default value. You also can't access them before you initialize them, before you assign them some value.

Well, this is more true for let rather than const. When you use const you have to declare it and initialize it. Some value is required. One interesting thing about var is that you can re-declare it as many times as you want. If you re-declare it in the same scope, the newer will overwrite the older.

This doesn't work with let and it also doesn't work with const. Try to re-declare let or const, in the same scope, and JavaScript will throw SyntaxError. It will say that some identifier has already been declared.

// Declare variable with var
// This will work flawlessly
var myVariableVar = 'first'
var myVariableVar = 'second'

console.log(myVariableVar)
// Output:
// 'second'


// Declare variable with let
let myVariableLet = 'first'
let myVariableLet = 'second'
// SyntaxError: Identifier 'myVariableLet' has already been declared


// Declare variable with const
const myVariableConst = 'first'
const myVariableConst = 'second'
// SyntaxError: Identifier 'myVariableConst' has already been declared
Enter fullscreen mode Exit fullscreen mode

Variable declaration and global object

There is one more difference in the terms of variable declaration between var and let and const. When you declare variable with var it will be bind to the Global object, Window in case of browser. This automatic binding doesn't happen if you declare variables with let and const.

// Declare variable with const
var myVariableVar = 'Global citizen'
let myVariableLet = 'mathematics'
const myVariableConst = 'change'

console.log(myVariableVar)
// Output:
// 'Global citizen'

console.log(myVariableLet)
// Output:
// 'mathematics'

console.log(myVariableConst)
// Output:
// 'change'


console.log(window.myVariableVar)
// 'Global citizen'

console.log(window.myVariableLet)
// Output:
// undefined

console.log(window.myVariableConst)
// Output:
// undefined
Enter fullscreen mode Exit fullscreen mode

Entering the temporal dead zone in JavaScript

You understand variables, scope and variable declaration and initialization. Now, let's finally talk about what the temporal dead zone in JavaScript is. In short, temporal dead zone describes a zone where variables are un-reachable. There are variables in the current scope. However, these variables were not declared yet.

Try to access those variables inside the temporal dead zone and JavaScript will throw a ReferenceError. This error will say that some variable is not defined. One thing to remember. Temporal dead zone exists only for let and const variables. These two variables exist in the temporal dead zone from the start until you initialize them.

This is also where the temporal dead zone is. Its beginning is at the beginning of the current scope at which you declared the variable(s). The end of it is where the variable is actually declared, where you assign that variable some value. The space between these two points is the temporal dead zone.

// Beginning of the global scope
// and also the beginning
// of the temporal dead zone for global variables
// The temporal dead zone for "myVariableLet" and "myVariableConst"
// The temporal dead zone for "myVariableLet" and "myVariableConst"
// The end of temporal dead zone for "myVariableLet" and "myVariableConst"
let myVariableLet = 33
const myVariableConst = true


// Example of accessing variable in the temporal dead zone
// Beginning of the temporal dead zone for "status" variable
// This is the temporal dead zone for "status" variable
// This is the temporal dead zone for "status" variable

// Try to access the "status" variable
// INSIDE the temporal dead zone
console.log(status)
// Output:
// Uncaught ReferenceError: status is not defined

// This is the temporal dead zone for "status" variable
// The end of temporal dead zone for "status" variable
let status = 'Jack'

// Try to access the "status" variable
// OUTSIDE the temporal dead zone
console.log(status)
// Output:
// 'Jack'
Enter fullscreen mode Exit fullscreen mode

Temporal dead zone and var

As usually, there is always some exception. This applies to temporal dead zone as well. The exception is the var. For var, there is no such a thing as a temporal dead zone. As you know, var has a default value of undefined. If you don't initialize it when you declare it, JavaScript will initialize it for you, as undefined.

// Try to access the "myVar" variable
// This will actually work
console.log(myVar)
// Output:
// undefined

// There is no the temporal dead zone for var

var myVar = 'Bug'

// Try to access the "myVar" variable again
console.log(myVar)
// Output:
// 'Bug'
Enter fullscreen mode Exit fullscreen mode

The cause of temporal dead zone

You know what the temporal dead zone in JavaScript is. Let's also quickly talk about why it exists. Whenever you run your JavaScript code it goes through two phases. The first phase is called compilation, or creation. During this phase, your code is being compiled into byte code.

The second phase is called execution. During this phase, your code is being executed. It is also during this second phase, the execution, when your variables are assigned their values. Back to the phase one, compilation. During this first phase another interesting thing happens.

During this phase, JavaScript engine goes through your code. It "collects" variables and allocates memory for them, and also for function declarations. It is at this moment, variables you declared with var are assigned the default value of undefined. Memory will also be allocated for let and const variables, but no values will be assigned.

This process of collecting declarations is called hoisting. This is also why the temporal dead zone exists, at least for let and const. In case of let and const, there is a moment when these variables are declared, but not initialized. Remember, declaration happens in the first phase, while initialization in the second.

This means that, during the first phase, let and const exist in the temporal dead zone. This is because they are not initialized with any value. On the other hand, the var is always initialized with the value of undefined by default. That's why it is never in the temporal dead zone.

When JavaScript engine enters the second phase it also initializes let and const variables. This is called compilation or creation. This is the moment when these variables can leave the temporal dead zone. Note that when this happens depends on when you initialize those variables in you code.

So, remember, all variables get hoisted. However, when var variables are hoisted they are also initialized with the value of undefined. When the let and const are hoisted they are not initialized with any value. That is the reason the temporal dead zone exists and why it exists only for let and const and not var.

Conclusion: Temporal dead zone in JavaScript explained

Temporal dead zone in JavaScript (TDZ) may sound complicated. It is not. It can be relatively easy. Especially if you understand how variables, scope and variable declaration and initialization work. I hope that this tutorial explained all these topics and helped you understand what temporal dead zone in JavaScript is and how it works.

Latest comments (2)

Collapse
 
drgaud profile image
DrGaud

Great Article man, thanks for explaining that to me man, I have been wondering why I would get caught out by that reference error. When I looked at my code I would see that I would declare something after calling it, 'TDZ', I often thought that It was a result of me writting it wrongly. This gives me a better sense of clarity to why Im getting that error.

Collapse
 
alexdevero profile image
Alex Devero

I'm glad it helped DrGaud.