Skip to content

var VS let VS const

Learning the meaning of frontend terminology

JavaScript 2015 (ES6) introduced let keyword.

Let’s introduce some important concepts.

The scope of a variable refers to the “region” of a program where the variable can be accessed and used. The scope determines where a variable is visible and can be referenced within the code.

A block is a chunk of code bounded by curly brackets {}.

Examples of blocks are functions or if statement bodies.

var declarations can be globally scoped or function/locally scoped.

The scope is global when a var variable is declared outside a function. This means that any variable that is declared with var outside a function block is available for use in the whole window.

The scope is local when a var variable is declared within a function. This means that it is available and can be accessed only within that function.

var name = "Pit";
function sayHello() {
var hello = "Hello: ";
console.log(hello + name);
}
console.log(name);
console.log(hello); // // error: hello is undefined

var variables can be re-declared and updated:

// re-declaration
var name = "Pit";
var name = "John";
// update
var name = "Pit";
name = "John";

Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their scope before code execution.

console.log(name); // name is undefined
var name = "Pit";

This is interpreted as:

var name; // hoisting
console.log(name); // name is undefined
var name = "Pit";

Let’s take the following code block:

var name = "Pit";
var days = 4;
if (days > 3) {
var name = "John";
}
console.log(name) // "John"

Since days > 3 returns true, then name is redefined to John.

This is not a problem if you intentionally want name to be redefined: it becomes a problem when you do not realize that a name variable has already been defined before.

If you have used name in other parts of your code, you might be upset at the output you might get. This will likely cause a lot of bugs in your code.

This is why let and const are necessary.

So basically let variables exist because of a lack of attention of frontend developers.

let is block scoped.

if (true) {
let name = "John";
console.log(name) // "John"
}
console.log(name) // name is not defined

Variables defined with let and const are hoisted to the top of the block, but not initialized. The block of code is aware of the variable, but it cannot be used until it has been declared.

Using a let variable before it is declared will result in a ReferenceError. The variable is in a “temporal dead zone” from the start of the block until it is declared.

if (true) {
console.log(name) // ReferenceError
let name = "John";
}

let can be updated but not re-declared:

let name = "Pit";
let name = "John"; // error: Identifier 'name' has already been declared

While updating is fine:

let name = "Pit";
name = "John";

If the same let variable is defined in different scopes, there will be no error:

let name = "Pit";
if (true) {
let name = "John";
console.log(name) // "John"
}
console.log(name) // "Pit"

Variables declared with const maintain constant values.

const cannot be updated or re-declared. Using a const variable before it is declared will result in a SyntaxError, so the code will not run.

const name = "Pit";
name = "John"; // error: Assignment to constant variable.
const name = "Diana"; // error: Identifier 'name' has already been declared

Every const declaration must be initialized at the time of declaration.

This behavior is different when it comes to objects declared with const. While a const object cannot be updated, the properties of the object can be updated.

// given this object
const person = {
name: "Pit",
age: 18
}
// the following assignment will cause
// error: Assignment to constant variable.
person = {
name: "John",
age: 25
}
// the following assigment won't cause errors
person.name = "John"

As already mentioned, const is hoisted to the top of the block, but not initialized.

ScopeRedeclareReassignHoisted
varNoYesYesundefined
letYesNoYesNot initialized
constYesNoNoNot initialized