Declaring variables in JavaScript since ES6 can be done in different ways. Most prominent of those are using var
, let
and const
.
1. Basic example on var
Consider the examples below:
/* Example 1 */
x = 10;
function updatex() {
x = 20;
}
updatex();
console.log(x); //20
/* Example 2 */
x = 10;
function updatex() {
var x = 20;
}
updatex();
console.log(x); //10;
In these examples, we see that declaring variables as var limits their scope to the particular function, in this case the function updatex()
. If we do not declare variable as var, it climbs up to global scope, declared and initializes itself there.
2. Example on var
and let
var
and let
are similar in nature, but are not the same. Let's consider following examples.
console.log(x); //undefined
console.log(y); //ReferenceError
var x = 10;
let y = 15;
In this example, we try to console log variables before they are declared in the program. var
variable logs undefined and let
variable throws an Uncaught ReferenceError. This happens because of hoisting.
Hoisting is JavaScript's default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function).
In this example, var
variable is hoisted to the top of the block, declared there, but not initialized, whereas let
variable is hoisted to the top of the block (i.e. the block of the code is aware of the variable) but it cannot be used until it has been declared. The time from which the variable is used till the time where the variable is initialized is called temporal dead zone.
3. Example on let
and const
So far we have seen direct declaration of variables, using var
and using let
. Now let's see const
. As you might have guessed, const
stands for constant. A constant is a variable which once declared and initialized remains the same and cannot be redeclared or changed through assignment. Does this mean const
is immutable? Not really, but we will check that out later. First let's see the behavior of let
and const
. Let's consider these examples:
/* Example 1 */
// we've seen this before
x = 10; //ReferenceError
let x;
/* Example 2 */
y = 20;
const y; //SyntaxError
/* Example 3 */
y = 20; //ReferenceError
const y = 20;
We've seen example 1. It throws a Reference Error. In example 2, y
being a const
variable throws a SyntaxError because after declaration, a const
variable must be immediately initialized. We cover this case in example 3, but as const
variables cannot be redeclared or reassigned, it throws a ReferenceError. So a proper way to declare const
variable would be:
const y = 20;
Both let
and const
have same scope properties. Unlike var
variables, let
and const
variables are hoisted but cannot be used until declared, and in case of const
, initialized. Now that you have a good understanding of scope and hoisting of different types of variables in JS, let's talk about immutability of const
variables.
4. Immutability of const
JS has 2 types of variables:
- Primitive types:
undefined
,null
,boolean
,number
,string
, andsymbol
- Reference types:
object
,array
andfunction
Declaring a const
variable to a primitive makes it immutable. But if it is initialized with a non-primitive or reference type, then it is possible to mutate the const
variable. Let's take a few examples:
/* Example 1 */
let arr1 = [10, 20];
arr2 = [30, 40]; // No error
const arr2 = [50, 60];
arr2 = [70, 80]; // SyntaxError, redeclaraion
/* Example 2 */
const arr2 = [50, 60];
arr2[0] = 70;
arr2[1] = 80;
console.log(arr2); // [70, 80]
As you can see, with respect to reference type variables, it's not possible to preserve their immutability.
5. Conclusion
var
variables are function scoped, let
and const
variables are block scoped. var
, let
and const
are hoisted, but let
cannot be used until declared and const
variables cannot be used until they are declared + initialized. const
variables, if initialized with reference types, are not immutable.
Outro
Enjoyed the article? Follow me on hashnode.
Connect with me: Twitter | LinkedIn
Thanks for reading!