Declaring variables is what we do most in JavaScript. Knowing the inside of the variable declaration process gives you more idea about it. For example, if you are new to JavaScript, the behavior of var
statement likely to be confusing for you.
Through this article, you will learn how to declare, and mutate variables using var
, let
, and const
statements, and have a better understanding of the differences between them.
I will explain each concept in two parts:
Before ES6 (
var
statement)After ES6 (
let
andconst
statements)
Let's dive into these statements:
Declaring Variables with Hoisting in Mind
When you declare variables in your app, the interpreter moves them to the top of their scope and allocates places in the memory before the execution starts. This process is called Hoisting.
1. Variable declaration with var
statement:
When you declare a variable with var
statement, it is initialized in the memory as undefined
before the code execution. So, you can use the variable before declaring it, but it returns undefined
.
When execution starts and reaches the line that the variable is declared, replaces the value in the memory with the value of the variable.
console.log(strawberry); // undefined
var strawberry = 'π';
console.log(strawberry); // π
With this behavior, the program runs without errors. However, in some cases, this can lead to unexpected results.
2. Variable declaration with let
and const
statements:
When you declare a variable with let
or const
statements the variable is allocated in the memory as uninitialized in the temporal dead zone. You cannot use variables in the temporal dead zone before their declaration. So, if you try to use a variable before declaring it, the program returns an error.
When the program reaches the line where the variable is declared, it initializes the variable with that value.
console.log(cherry); // ReferenceError
const cherry = "π";
console.log(cherry); // π
If you try to run this code snippet, you will see an error similar to below. Because we try to access a variable in the temporal dead zone.
Understanding Variable Scopes
In JavaScript:
- Everything between curly braces is block scope,
- Everything inside a function is function scope.
1. Scope of var
statement
Variables declared with var
statement are available globally. (If they are not declared in a function.) So, you can use the variables declared inner scope is in outer scopes and vice-versa:
// Global Scope
var carrot = "π₯";
// Inner Scope
{
console.log(carrot); // π₯
console.log(tomato); // undefined
// More Inner Scope
{
console.log(carrot); // π₯
var tomato = "π
";
}
console.log(tomato); // π
}
As you can see from the code snippet:
We were able to use the
carrot
variable declared in the most outer (global) scope in the inner scopes.We were able to use
tomato
variable declared in the inner scope in the outer scopes.
β Variables declared with var
statement in a function are only available in the function scope, and cannot be used outside of it.
// Function Scope
function declareMelon() {
var watermelon = "π";
}
console.log(watermelon); // ReferenceError
2. Scope of let
and const
statements:
The variables declared with let
and const
statements are only available in block scope.
const banana = "π";
// Block Scope
{
console.log(banana); // π
let lemon = "π";
// Inner Block Scope
{
console.log(banana); // π
console.log(lemon); // π
}
}
console.log(lemon); // ReferenceError
As you can see in the last line, you cannot use a variable created in the inner scope in the outer scopes.
Mutating Variables
This time the parts will change, the first group involves var
and let
statements and the second involves const
statement. Because var
and let
statements are mutable, and const
statement is immutable.
1. Mutation in var
and let
statements.
As I said var
and let
statements are mutable, so you can assign new values to the variables declared with them.
var pepper = "πΆοΈ";
let apple = "π";
pepper = "π«";
apple = "π";
console.log(pepper); // π«
console.log(apple); // π
Additionally, you can mutate a variable from inner scopes:
For
let
statement, the variable will change in the scope where the declaration is made.For
var
statement, the variable will change globally. (or in functional scope.)
{
pepper = "πΆοΈ";
apple = "π";
console.log(pepper); // πΆοΈ
console.log(apple); // π
}
console.log(pepper); // πΆοΈ
console.log(apple); // π
2. Mutation in const
statement
Variables declared with const
statement are immutable. So you cannot re-assign them.
const strawberry = "π";
strawberry = "π"; // TypeError
If you try to run the code snippet above, the program throws an error similar to below:
βImportant Note: You cannot mutate arrays and objects via assignment but can mutate them via their methods, and property assignment.
const fruitsArray = ["π", "π"];
const fruitsObject = {
apple: "π",
pear: "π",
};
fruitsArray[2] = "π"; // [ 'π', 'π', 'π' ]
fruitsArray.push("π"); // [ 'π', 'π', 'π', 'π' ]
fruitsObject.cherry = "π"; // { apple: 'π', pear: 'π', cherry: 'π' }
Redeclaring Variables
Strangely, we can redeclare variables declared with var
statement using the same name. This is another error-prone characteristic of var
statement. Fortunately, this behavior has changed with let
and const
statements.
1. Redeclaration with var
statement:
You can redeclare a variable declared with var
statement in the same scope or inner-outer scopes.
As I said before, variables declared with var
statement are global, so if you even redeclare a variable in the inner scope (again, except for functional scopes), the variable will change in all scopes.
var pepper = "πΆοΈ";
console.log(pepper); // πΆοΈ
// Inner Scope
{
var pepper = "π₯¦";
console.log(pepper); // π₯¦
}
console.log(pepper); // π₯¦
As you can see in the code snippet, This behavior tends to cause big problems. Because someone working in the same codebase, unintentionally may declare a variable using the same name used before.
2. Redeclaration with let
and const
statements:
You cannot redeclare variables declared with let
or const
statements in the same scope. If you try the program throws an error.
let eggplant = "π";
let eggplant = "π₯"; // SyntaxError
But you can redeclare the variables in inner scopes. Because, as I said before, the variables declared with let
and const
statements are block scope and don't affect the outer scopes.
const carrot = "π₯";
// Block Scope
{
const carrot = "π";
console.log(carrot); // π
}
console.log(carrot); // π₯
Conclusion
Today ES6 statements are the default choice for variable declaration in JavaScript. Nevertheless, the var
statement might still be encountered, especially in older apps. In this guide, you have learned the differences between var
, let
, and const
statements, hoisting and scope in variable declaration.
Thank you for taking the time to read this article. If you have any questions, or thoughts feel free to comment.
See you in the next one!
Stay in Touch
Resources
JavaScript Visualized: Hoisting by Lydia Hallie
JavaScript Visualized: Scope (Chain) by Lydia Hallie
Hoisting by MDN Web Docs