var vs let | let vs const
This post covers concepts related to the use of var, let and const keywords in ES6. We will compare based on the below various properties like scope, hoisting and accessibility, this, assignment and redeclaration, temporal dead zone and accessibility, and error handling.
Before jumping on to the applicable differences, let us first understand the meaning of "scope".
Scope
Scope of a variable is the region of your program in which it is defined/accessible, and is generally defined using a block using braces ({}).
NOTE: Scope is always associated with a declared identifier (such as a variable, a function, a class, or a parameter). It is not an independent entity; rather, it describes where that identifier is visible and can be accessed.
var is function-scoped & let is block-scoped
A variable declared using the var keyword belongs to the entire function, even if declared inside a block.
function test() {
if (true) {
var x = 10;
}
console.log(x);
}
test(); // logs 10
let belongs to the nearest block ({}).
function test() {
if (true) {
let x = 10;
}
console.log(x);
}
test(); // gives ReferenceError: x is not defined
Global var becomes a property of globalThis
In browsers, whether you do var x = 10; or globalThis.x = 10 both mean the same. But if one does:
let y = 20;
console.log(globalThis.y); // logs undefined
It does not create a property on the globalThis object. If x was declared with var, it exists. If it was declared with let, it doesn't.
Redeclaration
var allows redeclaration.
var a = 10;
var a = 20;
console.log(a); // logs 20
function example() {
for (var i = 0; i < 5; i++) { }
for (var i = 0; i < 10; i++) { }
}
// There is actually only one i variable.
// Each loop simply resets it.
let does not allow redeclaration.
let a = 10;
let a = 20; // gives SyntaxError
function example() {
for (let i = 0; i < 5; i++) { }
for (let i = 0; i < 10; i++) { }
}
// These are two different variables.
// Each loop gets its own _i_
Hoisting
Hoisting is probably the most confusing for beginners. Legacy JS used only var which is accessible even before declaration and assignment. Like below code:
console.log(x); // logs undefined
var x = 5;
Because it behaves similar to the below code:
var x; // initialize
console.log(x); // access
x = 5; // assignment
The declaration moves, the assignment stays where it is. As a result, we do not get any reference error.
However, later on we have let and const keywords which assist with meaningful errors without returning undefined.
console.log(x);
let x = 5; // ReferenceError: Cannot access 'x' before initialization
Why? Because the variable is placed in the Temporal Dead Zone (TDZ) until the declaration executes. Here, the variable exists in the memory but is not accessible for the code.
These have a number of benefits such as:
- It provides block scope, making variables behave more intuitively.
- It prevents accidental redeclarations.
- It avoids the confusing behavior of
varhoisting by enforcing the Temporal Dead Zone, so using a variable before its declaration results in a clear error instead of silently yieldingundefined.
Thanks for reading, if you came this far, please mention your thoughts / suggestions in the comments. Next article will cover optional chaining and short circuiting.
Comments
No comments yet. Start the discussion.