Var vs Let vs Const and the temporal dead zone
Explore the distinctions between var let and const declarations in JavaScript ES6 including their scoping rules and behavior. Understand the temporal dead zone concept that prevents access to let and const variables before they are initialized, improving code reliability and debugging. This lesson helps you know when and how to use each keyword effectively in your code.
We'll cover the following...
With the introduction of let and const in ES6, we can now better define our variables depending on our needs. During our JavaScript primer we looked at the basic differences between these 3 keywords, now we will go into more detail.
Var
Variables declared with the var keyword are function scoped, which means that if we declare them inside a for loop (which is a block scope), they will be available even outside of it.
Let’s take a look at an example with a functional scope variable:
In the first example, the value of the var leaked out of the block scope and could be accessed from outside of it. Whereas in the second example, var was confined inside a function-scope, and we could not access it from outside.
Let
Variables declared with the let (and const) keyword are block scoped, meaning that they will be available only inside of the block where they are declared and its sub-blocks.
The same example using var is given below.
As you can see, when we assigned a new value to the variable declared with let inside our block scope, it did not change its value in the outer scope. Whereas, when we did the same with the variable declared with var, it leaked outside of the block scope and also changed it in the outer scope.
Const
Similarly to let, variables declared with const are also block scoped, but they differ in the fact that their value can’t change through re-assignment and can’t be re-declared.
Important: This does not mean that variables declared with
constare immutable.
The content of a const is an object
In this case we are not reassigning the whole variable but just one of its properties, which works fine.
Note: We can still freeze the
constobject, which will not change the contents of the object (but trying to change the values of objectJavaScriptwill not throw any error).
The temporal dead zone
Now, we’ll have a look at a very important concept which may sound complicated because of its name, but I assure you it is not.
First let’s have a look at a simple example:
var can be accessed before they are defined, but we can’t access their value.
let and const can’t be accessed before we define them.
Despite what you may read on other sources, both var and let(and const) are subject to hoisting, which means that they are processed before any code is executed and lifted up to the top of their scope (whether it’s global or block).
The main differences lie in the fact that var can still be accessed before they are defined. This causes the value to be undefined. While on the other hand, let lets the variables sit in a temporal dead zone until they are declared. And this causes an error when accessed before initialization, which makes it easier to debug code rather than having an undefined as the result.
When to use Var, Let and Const
There is no rule stating where to use each of them, and people have different opinions. Here I am going to present to you two opinions from popular developers in the JavaScript community.
The first opinion comes from Mathias Bynens:
- Use
constby default - Use
letonly if rebinding is needed. varshould never be used in ES6.
The second opinion comes from Kyle Simpson:
- Use
varfor top-level variables that are shared across many (especially larger) scopes. - Use
letfor localized variables in smaller scopes. - Refactor
lettoconstonly after some code has to be written, and you’re reasonably sure that you’ve got a case where there shouldn’t be variable reassignment.
Which opinion to follow is entirely up to you. As always, do your own research and figure out which one you think is the best.
My personal opinion is to always use const by default and then switch to let if you see yourself in need of rebinding the value.