JavaScript Pills: var, let and const

Lari Maza
Lari Maza | En
Published in
4 min readOct 30, 2019
Photo by Samuel Zeller

[clique aqui para português]

This is a post from a series where I share insights from my journey with JavaScript in a mini article format. See all other posts on my profile!

Today, we have three keywords for declaring variables in JavaScript: var, let and const. The keyword var has always been around, but let and const are ES6 additions. The last two have virtually eliminated the need for var, which has lately become discouraged. Let’s find out why!

The main highlight of using const is that this type of variable, as the name implies, is constant: it cannot be redeclared and its value cannot be reassigned (this does not mean it is immutable; it can still change through other manipulations). Therefore, the value of every const must be assigned in the same statement as it was declared, since we cannot assign it later. Here’s what happens when we try to perform an illegal reassignment:

const juice = 'orange';juice = 'apple';
// Error: Assignment to constant variable

However, it is worth noting that, because it's not immutable, if const keeps an object, its keys and values ​​can be changed normally:

const myObj = { juice: 'orange' };myObj.juice = 'apple';myObj.juice
// 'apple'

Another difference between the three is that declaring a global variable (i.e. outside of a function) with var automatically adds it as a property of the window object:

var coffee = 'black';window.coffee === coffee
// true

However, declaring a global variable with let or const does not add it to the window object:

let tea = 'green';window.tea === tea
// false

In addition, both let and const declare a local variable within the scope of the block they are inserted into — unlike var, which ignores the block unless it is a function. A block is considered to be any brace {} delimited space. Here's an example of how let behaves in the scope of an if block:

let myNumber = 1;if (myNumber === 1) {
let myNumber = 2;
console.log (myNumber);
// 2
}
console.log (myNumber);
// 1

If we look it up from within the if block, the value of myNumber is the one that was assigned inside that block: 2. But if we reference it from outside the block, we have no access to the value that was assigned within it, since the variable is only available in that scope. We can only see the outside value of myNumber, attributed back at the example's first line: 1.

The same behaviour applies to const:

const myNumber = 1;if (myNumber === 1) {
const myNumber = 2;
console.log (myNumber);
// 2
}
console.log (myNumber);
// 1

This difference between scopes also affects the hoisting of the variables. Any variables declared with var are hoisted to the top of the function scope in which they were declared (or the global scope if they are not within any function). This means that the declaration (for example, var a) is executed before any other code, and even before the value is assigned:

function getMood (isHappy) {
if (isHappy) {
var happy = 'Yay!';
} else {
var meh = 'Meh';
}
}

In the above function, if we analyse the hoisting of the variables, this is what is happening in practice:

function getMood (isHappy) {
var happy, meh;
if (isHappy) {
happy = 'Yay!';
} else {
meh = 'Meh';
}
}

Can you imagine how this behaviour can return many accidental undefined's (and migraines)?

Here comes a big advantage of the let and const variables: because they consider the block in which they were declared as their scope, they behave differently. If the variable is declared within a block, it is suspended in the “temporal dead zone” until the declaration is processed, instead of being hoisted to the top. Ergo, the variable can only be accessed after its declaration. Sounds safer, right?

We can link this context to yet another particularity of let and const: they cannot be redeclared in the same scope and any attempt returns a syntax error. However, redeclaration at different scopes is accepted, because one context does not see the other. Here’s an example of valid code with let foo declared in two different blocks:

let myValue = 1;switch (myValue) {
case 0: {
let foo;
break;
}
case 1: {
let foo;
break;
}
}

When should we use each type of variable, then?

The decision between let and const depends only on whether you intend to reassign the value of this variable. Using const even improves the readability of your code by making it clear that such a variable is a constant.

In general: scoping, the ability to prevent value reassignment and the consequent reduced freedom in JavaScript (considered excessive by some) makes the use of let and const preferred by developers today to prevent accidental changes and breakage. The general convention is that there is no reason to use var anymore.

Keep in mind that there are still other differences and more advanced features. If you'd like to dive deeper, you should refer to the MDN specifications for let and const.

That’s all for today and see you next time ❤

--

--