Understanding Var, Let, and Const in JavaScript

The short answer:

Var

Let

Const

The long answer:

There are 3 ways to declare variables in JavaScript: var, let and const. Here are the key differences between var, let and const.

1. Var declarations are function scoped. Let and Const are block scoped. Function scope is created by declaring a function. Block scope is created by if statements, for loops, while loops etc. Let’s understand this with an example.

// Function Scope
function isLoggedIn(user) {
var friend = "pete";
let isLoyal = true;
const pi = 3.14;
// Block Scope
if (user) {
var name = "tom";
let age = 23;
const sex = "male";
}
console.log(name); // Tom
console.log(age); // ReferenceError
console.log(sex); // ReferenceError
}
console.log(friend); // ReferenceError
console.log(isLoyal); // ReferenceError
console.log(pi); // ReferenceError

In the above example, we have a function isLoggedIn with some variable declarations within the body of the function. The variable declarations `friend`, `isLoyal`, and `pi` are declared within the body of the function and may be used anywhere within the function isLoggedIn. When we try to access these variables outside of the function body as we tried on lines 17, 18, and 19, we receive a ReferenceError. This is because all variable declarations within a function are only accessible within the scope of that function.

But when we introduce a block scope within our function as we did on line 7 and declare the variables “name”, “age”, and “sex”. We are able to access only the variable declared with var outside of the if statement(block scope). Hence, var declarations are function scoped. And let and const are block scoped.

for (var i = 0; i < 10; i++) {
console.log(i); // i is visible so we get 0,1,2,...,9
}
console.log(i); // i is visible here too. so we get 10
for (let j = 0; j < 10; j++) {
console.log(j); // j is visible so we get 0,1,2,...,9
}
console.log(j); // throws an error

In this example, we have 2 for loops in the global scope. In the top for loop, since the variable ‘i’ is declared with var, ‘i’ is accessible in the global scope after the for loop is finished running. This is why we get 10 outside the scope of the for loop.

This means that if a variable is declared using var anywhere besides a function, it will always exist in the global scope.

In our second for loop, because ‘j’ is declared with let, we are unable to access ‘j’ outside of the for loop.

2. Var allows duplicate identifiers. Let and Const do not allow duplicate identifiers.

var name = "pablo";
var name = "john";
// cannot do this with let or const or you will get a SyntaxError

Variables with var can be re-declared. But doing the same with a let or const will lead to a SyntaxError.

3. Values declared with Var and Let variables can be re-assigned. Values declared with const variables cannot be re-assigned.

var num = 3;
num = 4;
let age = 55;
age = 56;
const pi = 3.14;

In the above example, we are able to change the value of a variable declared with var and let but not with const.

4. Var declarations are hoisted and initialized with undefined. Let and Const are hoisted but not initialized with undefined.

function Add() {
console.log(answer); // undefined
var answer = 2;
}
Add();
function Subtract() {
console.log(answer); // ReferenceError
let answer = 2;
}
Subtract();
function Multiply() {
console.log(answer); // ReferenceError
let answer = 2;
}
Multiply();

Variable identifiers are hoisted AND initially are set to undefined. This is why the answer variable will display as undefined in the Add function.

In the Subtract and Multiply functions, Let and Const declarations are hoisted BUT we would get an error because we cannot access answer before declaration.

This is because of a Temporal Dead Zone (TDZ) for let and const declarations. The Temporal Dead Zone is a time window where a variable exists but is still uninitialized. And because this variable is uninitialized , it is unaccessible.