Everything you need to know about Variables in JavaScript

Everything you need to know about Variables in JavaScript

var, let and const in JS

This blog aims to explain variables, other related concepts, and the differences between var, let, and const in-depth and in the simplest possible manner.

What are variables in JavaScript?

Variables are like named containers that store a value inside of them.

These variables can contain the following:

  • a variable keyword like var, let, and const.

  • name of the variable for example myName

  • an assignment operator =

  • and finally the value of the variable

  • The value of the variable can be a string, number, boolean, other primitive types, arrays, objects, and even functions

// for example
const myName = "Amulya";

Major related concepts in JavaScript

Important Terms

Oftentimes, we come across words like "initialization", "declaration", "assignment", "reassignment", "redeclaration" and so on. But we don't understand what they mean.

Declaration

Declaring variables in JS is like saying from now on these variables exist in this JavaScript code.

// for example
var a;
let country;

// These variables have been declared

Initialization

Variable Initialization is used interchangeably with assignment, it is like initializing a variable with a value and storing it. Initialization takes place on the same line as the declaration and assignment.


var color; // the variable is not initialized yet but will not give an error

let name; // the variable is not initialized yet but will not give an error 

let city = "Paris"; // It was initialized and was assigned a value "Paris" at this line.

let name = "Marilyn"; // The previously declared variable was initialized and was assigned a value "Marilyn" at this line.

const myName; //  the variable is not initialized yet but it will give an error, Uncaught SyntaxError: Missing initializer in const declaration 

const myname = "Amulya"; // const has to be assigned a value. In conclusion, const is declared, assigned, and initialized all at the same time.

Assignment

Variable assignment is to store a value in the variable. It is done with the assignment operator =. The value that is given to the variable can be any datatype like a string, number, object, function, etc.

// for example
var a = 5; // a is assigned the value of 5 
let country = "India";  // country is assigned the value of "India"

Redeclaration

Redeclaration means to declare again a variable that has already been declared earlier.

// for example
var a = 5;
var a = 100;
console.log(a);
// gives us 100 in the console

// if you did this
var a = 100;
var a;
console.log(a);
// it will NOT give us undefined (unless you explicitly assign undefined to a) because var 'a' already has the value of 100

In JavaScript, only a variable with the var keyword can be redeclared without an error. Redeclaring in JavaScript does not mean giving it a new memory space, the memory space allocated to the originally declared variable stays the same. The new value simply overrides the old value.

Reassignment

Reassignment means to give an already declared variable a new value. This can be done in the case of var and let.

// for example

let b = "Hey there";
b = "Bye";
console.log(b); // gives us the new value "Bye"
Declaration (without assignment)Initialization / AssignmentReassignmentRedeclaration
var a;var a = 10a = 100var a = 1000
let b;let b = 20b = 200Not allowed
Not allowedconst c = 30Not allowedNot allowed

We will individually see all these cases for var, let, and const ahead in the blog.

Scope

Scope is the reach of the variable. That means the scope is the limit up to which the variable can be used/ accessed. Ask yourself:

Where can I use this particular variable? And the limits of that answer mark the variable's scope.

JavaScript has 3 types of scopes: Global scope, Function scope, Block scope

Global scope

Global Scope consists of all variables in the global space. Global space is space outside the functions and blocks. It is the space from which all the functions can borrow a variable. It contains all var variables outside of functions and all let and const variables outside of functions and blocks.

var fruit1 = "Litchi" // global variable - global space
let fruit2 = "Orange" // global variable - global space
const fruit3 = "Mango" // global variable - global space
function containingFruits(){
console.log(fruit1, fruit2, fruit3) // Litchi Orange Mango
// can use global variables in here
let newFruit = "Blueberries" // function scoped variable - inside a function
console.log(newFruit) // Blueberries
}
console.log(newFruit) // ReferenceError (newFruit is not defined here outside the function)

Function scope

Function scope is the scope inside a function. Variables declared inside functions are limited/restricted to the functions.

// for example

function createColour(){
var colourCreated = "blue"
let anotherColour = "red"
const yetAnotherColour = "yellow"
console.log(colourCreated, anotherColour, yetAnotherColour ) 
}
createColour() // blue red yellow
console.log(colourCreated, anotherColour, yetAnotherColour ) // Reference Error 

// The console.log() outside the function gives a reference error because the variables simply don't exist outside the scope(reach) of the function.

Block scope

Block scope is the scope inside a block. A block is simply a block of code inside curly braces {} without the function keyword. A block can be the area inside the curly braces in conditionals (if and else statements), curly braces in a loop, or simply {}. (This concept exists in ES6 for let and const.)

//1
let aVariable = "hey" // This is one variable
{
let aVariable = "hello" // This is another variable
console.log(aVariable) // "hello" is printed in the console
}

console.log(aVariable) // "hey" is printed in the console

//2 
for (let i= 0; i <= 10; i++){
console.log(i) // prints numbers from 0 to 10
}
console.log(i) // Gives a ReferenceError that "i" is not defined

The explanation for 1: Even though the two variables "aVariable" inside and outside the curly braces might look the same, they are different variables with different memory locations and are in different scopes.

The explanation for 2: The reference error that "i" is not defined, is because the scope of "i" is limited to the block scope of the for loop.

//for var: new code
//3
var aVariable = "hey" // This is one variable
{
var aVariable = "hello" // This is the same variable
console.log(aVariable) // "hello" is printed in the console
}
console.log(aVariable) // "hello" is printed in the console

//4 
for (var i= 0; i <= 10; i++){
console.log(i) // prints numbers from 0 to 10
}
console.log(i) // Gives "undefined"

//5
let aVariable = "hey" // This is one variable
{
aVariable = "hello" // This is the same variable
console.log(aVariable) // "hello" is printed in the console
}
console.log(aVariable) // "hello" is printed in the console

The explanation for 3: For variables with the var keyword, the variable remains the same and is updated to a new value even if it is in a block.

The explanation for 4: The fact that JavaScript gives us "undefined", means that it knows the variable "i" exists somewhere in the memory. (Undefined is not an error)

The explanation for 5: If you try this in the Chrome browser console: It prints two 'hello'. Why is this? Let me tell you! The 'aVariable' inside the block is another variable with a default value of var. And var is not block scoped: When we try to access it outside the block, the browser thinks you are trying to use the latest variable (var aVariable = "hello") and thus it prints "hello".

Scope of var, let, const

  • var is function scoped (limited/restricted by functions)

  • let and const are block scoped (limited/restricted by blocks of code)

Undefined

Undefined is a special keyword in JavaScript. For all var and let variables, if you just declare a variable without assignment to a value, JavaScript automatically gives an initial value, a keyword "undefined" to the variable. It acts as a placeholder until the actual value is given to the variable.

Undefined is not an error. Not defined is an error. These both have very different meanings. Not defined is to say the variable does not exist. And undefined is to say the variable exists but is not yet assigned a value.

const cannot have undefined as a value because you cannot declare a const variable without assigning it a value. It gives a Syntax Error as 'Uncaught SyntaxError: Missing initializer in const declaration'.

var a;
console.log(a); // undefined
let b;
console.log(b); // undefined
const c;
console.log(c); // Uncaught SyntaxError: Missing initializer in const declaration

Hoisting

In hoisting, JavaScript processes declarations (of variables and functions) before any code is executed and gives them a memory space. So imagine there is some code in a file, even before the code runs, JavaScript gives a memory space to the variables.

console.log(a); // undefined
var a = 10;

Explanation: When we try to access the var variable before declaring it, it gives us the keyword "undefined", which means that "a" has taken up space somewhere in the code. We can access it even before initialization.

console.log(b); // It gives us a ReferenceError: Cannot access 'b' before initialization - we discuss this ahead
let b = 10;

// same goes for const

Explanation: When we try to access the let and const variables before their initialization, they give us a Reference error. Let's see why ahead.

Because of the above phenomenon, people have a major misconception in the JS community that let and const are not hoisted(not allocated memory space)!

But the truth is:

var, let, and const, all three are hoisted!!!

Let and const are hoisted differently than var. For understanding this, you have to understand the Temporal Dead Zone.

Temporal Dead Zone

When we try to access a variable with a const or let keyword before we have declared it, it gives us an error.

console.log(c); // Uncaught ReferenceError: Cannot access 'c' before initialization
let c = "Hello World";
console.log(d); // Uncaught ReferenceError: Cannot access 'd' before initialization
const d = "Hey There";

Why does this happen?

This explanation is only for let and const variables. When you try to access "c" and "d" before they have even been declared, they are in a "temporal dead zone". Temporal Dead Zone(TDZ) is the time between when we try to access a variable and when it is declared/initialized. As the name suggests, for this time, the variables act as if they are temporarily dead but they do exist somewhere.

They are hoisted, and they do take up memory space but you cannot use them before their declaration, that is, they are not initialized (Remember: Initialization happens when you declare a variable and store a value in it. You cannot use let and const before declaration).

// here const d = "Hey There" is in temporal dead zone and cannot be initialized/accessed
console.log(d);
const d = "Hey There";
// let is also in the temporal dead zone and cannot be initialized with undefined or a value before it is declared
console.log(c);
let c = "Hello World";

For let and const:

Declaration -----> Temporal Dead Zone -----> Initialization

For var:

Given initial value undefined -----> No TDZ ----> Declaration + Initialization

In the case of var variables, they do not have a temporal dead zone. They can be accessed even before their declaration and initialization with the special keyword undefined.

var variables are given memory like let and const but the difference is you can use var even before it is declared.

// here var a = undefined already exists and can be used
console.log(a);
var a = 10;

var is allocated memory in the global memory space. let and const are allocated memory in another space. (This is the reason why they are hoisted differently)

var, let, const in JS

var

var is a keyword from ES5. It is an old way to declare a variable.

No Error/correct: ✅ Error/wrong use: ❌

var

code/reasoning

additional info

When to use:

Try to avoid its usage as much as possible❌

ES5 and you can run into unknown errors and confusion in your code.

Declaration without assignment :

var name; ✅

-

Assignment:

var name = "William"; ✅

-

Redeclaration:

var name = "James"; ✅

only var variables can be redeclared

Reassignment:

name = "Mary"; ✅

-

when simply declared without value it gives:

undefined; ✅

-

Scope

Function scoped✅

When in a function its reach is limited to the function. In a block, it is not restricted/limited.

is Hoisted?

Yes ✅

given memory space

Initialization

Done with declaration ✅

-

Initialization before declaration

It can be accessed before declaration ✅ (of course, assuming it exists somewhere in the code)

It returns undefined when we access it before declaration.

let

let is a keyword from ES6. It is a new way to declare a variable when you want to change it in your code later on.

No Error/correct: ✅ Error/wrong use: ❌

let

code/reasoning

additional info

When to use:

Use only when you want to modify the variable later on.✅

ES6 and preferred over var

Declaration without assignment :

let name; ✅

-

Assignment:

let name = "William"; ✅

-

Redeclaration:

let name = "James"; ❌

Uncaught SyntaxError: Identifier 'name' has already been declared

Reassignment:

name = "Mary"; ✅

-

when simply declared without value it gives:

undefined; ✅

-

Scope

Block Scoped ✅

In a block, the scope(reach) of let variables is restricted/limited to the block. In functions, they act the same as var.

is Hoisted?

Yes ✅

given memory space

Initialization

Done with declaration ✅

-

Initialization before declaration

It cannot be accessed before declaration because it is in a temporal dead zone❌ (of course assuming it exists somewhere in the code)

Uncaught ReferenceError: Cannot access 'name' before initialization

const

const is a keyword from ES6. It is a new way to declare a variable when you want to keep the variable constant throughout the code.

No Error/correct: ✅ Error/ wrong use: ❌

const

code/reasoning

additional info

When to use:

Use it when you do not want to modify the variable later on and keep it constant.✅

ES6 and best practice when you do not want to change your variable.

Declaration without assignment :

const name; ❌

Uncaught SyntaxError: Missing initializer in const declaration. As soon as a const variable is declared, it must be given a value (must be assigned).

Assignment:

const name = "William"; ✅

-

Redeclaration:

const name = "James"; ❌

Uncaught SyntaxError: Identifier 'name' has already been declared

Reassignment:

name = "Mary"; ❌

Uncaught TypeError: Assignment to constant variable.

when simply declared without value it gives:

undefined; ❌

It cannot be declared without a value🚫. Thus, undefined is never seen in the case of const.

Scope

Block Scoped ✅

In a block, the scope(reach) of let variables is restricted/limited to the block. In functions, they act the same as var.

is Hoisted?

Yes ✅

given memory space

Initialization

Done with declaration ✅

-

Initialization before declaration

It cannot be accessed before declaration because it is in a temporal dead zone❌ (of course assuming it exists somewhere in the code)

Uncaught ReferenceError: Cannot access 'name' before initialization

Comparison Time

varletconst
ECMAScript versionES5ES6ES6
Declaration without assignmentSyntaxError
Assignment
RedeclarationSyntaxErrorSyntaxError
ReassignmentTypeError
ScopeFunction scopeBlock scopeBlock Scope
Is it Hoisted?
Can I access it before declaration?✅ gives undefined No Temporal Dead ZoneReferenceError Temporal Dead ZoneReferenceError Temporal Dead Zone
Strictnessflexiblestrictstrictest
Should I use it?No❌Can✅Can✅✅

Good Practices

  • Declared all variables at the top of the scope you are in, this will help avoid the Temporal dead zone in case of let and const. It is recommended to not use var, but in case you are this step will avoid the word 'undefined'.

  • The same names should not be allocated to different variables so that there is no confusion.

  • You should always use const unless you need to modify your variable later

  • You should use let when you need to modify your variable later

  • You should avoid using var. "Why," you ask. Because in case your code starts behaving unpredictably, you will not be able to diagnose the problem. var is way too flexible for its own good. But in the case of let and const, you get errors that inform you beforehand if you are doing something wrong. This makes it easy for you as a developer.

use:

const > let > var

Hope you enjoyed reading this blog! Would love to get your feedback!😊