The Difference Between var, let and const in JavaScript: Part 2

Back to the basics with variables and scope

Joe Cardillo
4 min readJun 6, 2018
It’s just a beautiful photo and has nothing to do with JavaScript, by Badder Manaouch on Unsplash

In a previous post I discussed some of the differences between var, let and const.

This post goes a little deeper into differences between the three. So hold on to your consoles!

The Differences Between let and var

A var variable can be redeclared and updated.

A let variable be be updated but not redeclared.

An example of trying to redeclare a let variable:// In editor:<script>
let points = 50;
let points = 60;
</script>
// In the console I get an error:
Uncaught SyntaxError: Identifier 'points' has already been declared

However, I can update it:

let points = 50;
points = 60;
// In console:
points
// Returns:
60

The Scope of let

If I declare a let variable at the global scope, then redeclare it within a block (curly brackets) as in the example below, I will not get an error in the console, but it will not actually redeclare let.

let points = 50;
let winner = false;
if(points > 40) {
let winner = true;
}
// If I call:
winner
// It returns the first value:
false

Why is this happening?

Because let winner = false and let winner = true, are actually two separate variables because they are scoped differently, even though they have the same name. To clarify:

// This 'let' is scoped to the window (globally):
let winner = false;
if(points > 40) {
// This 'let' is scoped to the block (between the curly brackets):
let winner = true;
}

In the above example if we change bothletvariables to var, then call winner in the console it returns true because it is not inside a function. (Remember: var is function scoped.) The var variable is being redeclared within its scope, which is the window in this case.

let points = 50;
var winner = false;
if(points > 40) {
var winner = true;
}
// If I call:
winner
// It now returns:
true

The Differences Between let and const

const variables cannot be updated. let variables are made to be updated.

// If I define the const variable:
const key = 'xyz123';
// Then try to redeclare it:
key = 'xyz1234'
// I get the following error:
Uncaught TypeError: Assignment to constant variable.

There is an interesting caveat to this, though. If I create a const variable that is an object, the attributes of that object can be updated.

// Creating my person object:
const person = {
name: 'Joseph',
age: 33
}
// Calling person in the console:
person
// It returns:
{name: "Joseph", age: 33}
// If I then redeclare the age attribute:
person.age = 34
// When I call it:
person
// It returns:
{name: "Joseph", age: 34}

Note: If I want to make object unchangeable I could “freeze” it:

const joseph = Object.freeze(person);

If I then try to change an attribute of the person object in my console, it does not take the changes:

// If I call:
person
// It returns:
{name: "Joseph", age: 33}
// However, if the object has been 'frozen' and I try to change the age attribute:
person.age = 34
// It will immediately return:
34
// But then when I call it:
person.age
// It returns the original age:
33

The advantages of using let vs. var in a for loop

I’ve run into many issues regarding scope with for loops when defining i with var. This is where using let could prove advantageous.

// Running a for loop with var:
for(var i = 0; i < 10; i++){
console.log(i);
}
// Returns 0 through 9 in the console, but if I call:
i
// It returns:
10

In other words, i has leaked out of the scope of the for loop, and can now be called at the global scope (or whatever the parent scope is)!

The other issue with using var in a for loop is when you want to do something within the scope of the loop, but after the loop runs. i is being redeclared each time the loop runs.

// Do something one second after the loop runs:
for(var i = 0; i < 10; i++) {
console.log(i);
setTimeout(function() {
console.log('The number is ' + i);
}, 1000);
}
// If we then call i in the console it returns:
10

Again, the variable i is being overwritten every time the loop runs. By the time setTimeout runs, i is 10.

A quick way to fix this is the change var to let. Because let is block scoped (within the curly brackets), it will behave differently, and will not reassign i every time the loop runs:

for(let i = 0; i < 10; i++) {
console.log(i);
setTimeout(function() {
console.log('The number is ' + i);
}, 1000);
}
// This returns 0 through 9 in the console, then after one second logs:
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8
The number is 9

--

--