Var, Let and Const
Before es6 only var was used to declare variables in JS, but with es6 came let and const. There were many problems related to var and thus it was necessary to have a new way of variable declaration.
Var
- var can be scoped globally and locally.
- var variables can be re-declared and updated
- var is hoisted and initialised to "Undefined"
Problems with Var
- In large codebases you many not know if a variable has been initialised a value and you may accidentally change the state of a var variable resulting in wrong outcomes.
Let
- let is block scoped
- let behaves as different declarations in different scopes
- let can be updated but not re-declared
- let isn't initialised on being hoisted
Const
- Variables declared with the const maintain constant values
- const declarations are block scoped too
- const cannot be updated or re-declared so if there's a need of a variable whose value should never change like Birthdays a const variable declartion comes handy
- const must be initialized at the time of declaration.
- const variables can't be updated but const object properties can!
Block Scope
In Javascript, we can use { } to add a new level of scope anywhere. Let and const are both block scoped. It means they can only be accessed within the "{ }" scope surrounding them.
Var on the other hand is not blocked scope.
These examples will show you what block scope of let and const means.
let z=3;
let u=true;
if(u)
{
let z=4;
}
console.log(z)
3
const z=3;
const u=true;
if(u)
{
const z=4;
}
console.log(u);
3
var z=3;
var u=true;
if(u)
{
var z=4;
}
console.log(z)
4
let and const are limited to their scope and do not exist outside the scope.
What happens if a variable is accessed before being initialized?
Do you know why it came undefined for logging var value and Reference Error for logging let value?
The same thing happens with const too!
Let's see what's exactly happening here.
TDZ (Temporal Dead Zone)
When a variable is declared inside the scope but is inaccessible somewhere in the scope, that zone of the scope is called TDZ.
{
/* ******* TDZ ******* */
console.log(name);
/* ******* TDZ ******* */
let name = "Aniket";
Uncaught ReferenceError: Cannot access 'name' before initialization
}
{
/* ******* TDZ ******* */
/* ******* TDZ ******* */
let name = "Aniket";
console.log(name);
Aniket
}
You can easily see that accessing the variable name before being declared gives the ReferenceError. This happens because of the TDZ. But this does not happen with var as it is default initialized to "undefined";
Please remember the difference between being declared and being initialized too. let and const variables exist in the TDZ from the start of their enclosing scope until they are declared.
Why is there a TDZ for let and const but not for var?
This happens because of Hoisting. While parsing the code to convert it into the AST(Abstract Syntax Tree) the JS engine apparently moves all the variable declarations to the top of the scope, but if this happens how are let and const not accessible? As i wrote in the starting of the blog this is because of the fact that when JS Engine hoists these variable declarations it initializes the var variable declarations to undefined but this does not happen with let and const variable declarations.
Let and const are hoisted too just in case you think they're not. I repeat the JS Engine doesn't initialize let and const to undefined upon being hoisted.
This small detail is the reason TDZ exists for let and const!
Always remember to declare your let and const at the top of the scope to escape the wrath of TDZ! :)
If you liked the article or have any suggestions for me please reach out on @aniketxparihar at Twitter! :)