With ES2016 came two new methods to declare variable i.e. let
and const
. Before that the developers had access to only var
(I feel bad for them, no kidding).
So, what's the catch here? Why are there three different ways to declare variables? Wasn't JavaScript already confusing enough and now they're making it more confusing.
Before we can understand how var
and let/const
differ we need to understand a computer science-y concept called scope
.
Function scope vs Block Scope
JavaScript comes with two kinds of scope i.e Function scope and block scope. Let's have a look at the difference in both of them.
Function Scope
function myFn() {
var foo = 'peekaboo!';
console.log(foo); // 'peekaboo!'
}
console.log(foo); // ReferenceError: foo is not defined
Variables are function-scoped when using var because their visibility is restricted to the function. You'll get an error if you try to utilise it outside of the function.
Block Scope
if (true) {
var foo = 'peekaboo!';
let bar = 'i see u';
const baz = 'baby blue!';
console.log(foo); // 'peekaboo!';
console.log(bar); // 'i see u';
console.log(baz); // 'baby blue!';
}
console.log(foo); // 'peekaboo!';
console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // ReferenceError: baz is not defined
Notice the visibility of foo isn’t limited by the if-statement block. However, both bar
and baz
are limited in visibility to the block of code.
This concept of scope is the most prominent distinction between the old-fashioned var
and modern let/const
.
Source: https://twitter.com/mpjme
VAR
Let's have a look at the following code snippet
for (var i = 0; i < 3; i++) {
console.log(i);
}
console.log(i);
According to you what will be the output of the following program??
If you said
//0
//1
//2
//3
then you're absolutely correct.
The variable i
is accessible outside of the for-loop. This is expected since variables defined with var have a function scope rather than a block scope i.e they're accessible within the whole function in which they are defined in.
If it's so cool then what's the problem with using var? Why aren't we using it?
I'll use the example below to explain:
var greeter = "hey hi";
var times = 4;
if (times > 3) {
var greeter = "say Hello instead";
}
console.log(greeter) // "say Hello instead"
So, since times > 3
returns true
, greeter is redefined to "say Hello instead". While this is not a problem if you knowingly want greeter to be redefined, it becomes a problem when you do not realise that a variable greeter has already been defined before.
If you have used greeter in other parts of your code, you might be surprised 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.
In layman terms, var
can be redefined and it's values can also be changed?
So Shubhra, what can we do to save ourselves from making such blunder in production code???
Well, worry not, the people in the JavaScript headquaters knew that you would be having this problem and already gave a solution for this.
Here comes let
to save the day.
LET
In many ways let
is like a cousin of var
. It has a lot of similarities but differentiates in ways that makes ES2016 a more modern-feeling language.
Let us take the same example we took in var
for (let i = 0; i < 3; i++) {
console.log(i);
}
console.log(i);
This time what do you think the output is going to be?? Well if you said
//0
//1
//2
//ReferenceError: i is not defined
then you're in luck.
Hey Shubhra, if let
is a cousin of var
then why is it coming undefined?
Let me tell you, so let
is blocked scope instead of being function scoped.
let can be updated but not re-declared.
Just like var
, a variable declared with let
can be updated within its scope. Unlike var
, a let
variable cannot be re-declared within its scope. So while this will work:
let greeting = "say Hi";
greeting = "say Hello instead";
this will return an error:
let greeting = "say Hi";
let greeting = "say Hello instead"; // error: Identifier 'greeting' has already been declared
However, if the same variable is defined in different scopes, there will be no error:
let greeting = "say Hi";
if (true) {
let greeting = "say Hello instead";
console.log(greeting); // "say Hello instead"
}
console.log(greeting); // "say Hi"
Why is there no error? This is because both instances are treated as different variables since they have different scopes.
This fact makes let
a better choice than var
. When using let
, you don't have to bother if you have used a name for a variable before as a variable exists only within its scope.
Also, since a variable cannot be declared more than once within a scope, then the problem discussed earlier that occurs with var
does not happen.
CONST
The keyword const
is an abbreviation for constant. Similar to let
, it’s block-scoped, however, you can’t reassign it.
What do you think is the output of this code?
const myBoolean = true;
if (myBoolean) {
const turtles = [
'leonardo',
'donatello',
'michaelangelo',
'raphael'
];
// turtles = turtles.concat('Shredder'); // 🙅♀️ this would throw an error
console.log(turtles);
}
console.log(turtles);
The output
// ['leonardo', 'donatello', 'michaelangelo', 'raphael']
// ReferenceError: turtles is not defined
Because the const
is not transferred in this scenario, items can still be added to a const variable that links to an array or an object.
This is a topic for another blog. I will discuss it later.
Conclusion
Because function-scope isn't as evident as block-scope, it's best to avoid using var
. The objective of ES2016-2019 appears to be to replace var
with let/const
because they encourage better code habits.
If you need to construct a variable, you should usually use const. Use let instead if you know or suspect you'll need to reassign it (for-loops, switch statements, algorithm swapping).
Top comments (1)
Nice summary and I admire your curiosity and diligence in exploring it. For my part I simply accepted that var is essentially deprecated and let and const its modern replacements. I won't change that, meaning I have avoided using var for ages and routinely replace it with let or const as appropriate (and retest).