This post is part of learning ES6 series.
Let's look at the differences between
const in ES6 today.
var has been around since the beginning, and
const were introduced recently in 2015.
In order to understand what benefits
const provide, you have to understand the quirks of
var which has led to many subtle (and many not so subtle) bugs.
Problem #1 - redeclaring variables
You can re-declare a variable using
var and the compiler won't yell at you for doing this. 🤨
Re-declared the variable length without breaking a sweat
This is problematic especially for short lived variables like the ones used in loops( i, j, k), because you can end up accidentally re-using the values assigned to the previously declared variable.
Problem #2 - scoping
var variables are scoped to the "current execution context" i.e. the variable's enclosing function or the global scope. It is NOT a block scoped variable. Let's look at an example to make this clear.
To make the
var function scoping concept more concrete, if you try to access the variable
i outside the
varTest() function, the compiler will throw an error.
Problem #3.1 - Accidentally scoping the variable to the global scope
It is very easy to create a
var variable against the incorrect scope, here we've created a global variable attached to the
window object - seniorityLevel.
This happens because
var variables (outside of a function) are attached to the global window object.
Problem #4 Use it before you declare aka Temporal Dead Zone
var you can be a magician and use a variable before it even exists.
Now, lets see how
const address these problems.
You cannot re-declare
let variables within the same execution context. If you try to do this, the compiler will tell you off.
However, you can re-declare
let variables, if they are in different execution contexts (fancy way of saying different blocks or functions). What does this mean? The following example will run fine without any issues:
As expected, since the variable
winner is re-declared, it does not say
true in the final console.log(). This is because they are scoped differently, the
winner on line 11 is scoped to the window object and the
winner on line 15 is scoped to the if block.
As an exercise for you, dear readers, change the
letinside of the if block to
varto see what the compiler does. Will it throw an error message or will it work (silently)?
let is block-level scoped instead of function or globally scoped. If we take the same example as
var above and use
let instead, we get an error as we should.
And no more leaking of
for loop variables.
It doesn't just avoid issues like these described above, it also gives us an easy way to create block level "private" variables like this:
let you can say goodbye to all those pesky
var bugs, including the temporal dead zone bug, because you cannot use or reference a
let variable before declaring it.
const has the same features as
let - it's block scoped and cannot be re-declared within the same execution context, however (as the name suggests), you use
const to declare CONSTANTS (i.e. variables whose values don't change).
There is a subtlety that you need to be aware of.
const is not about immutability (that gets all the functional programmers unnecessarily excited), instead it creates an immutable binding.
const variable is assigned to an array or an object, you can still change the values of the object's properties and add / remove values to the array.
The thing that's immutable in both examples above is the binding.
const guarantees that no rebinding will happen once it assigns a value to a variable name. In the case of arrays and objects, their internal state can change.
Note: If you want to declare a
constwhose binding and internal state is truly immutable, you can use Object.freeze() to achieve this outcome.
const were added to the ECMAScript specification, you would get around the
var issues by using hacks like IIFE to isolate variable declarations so that they don't (inadvertently) pollute the global object name-space.
Unless you have a requirement to support very old browsers, I'd strongly suggest avoiding
var like the plague. You don't need it anymore as you have safer alternatives in the form of
I like (and recommend) Mathias's approach to using
var as follows:
- use const by default
- only use let if rebinding is needed
- (var shouldn’t be used in ES2015+)
Thanks for taking the time to read this post, if you found it useful and if you have any comments or tips, please hit me up on twitter (@anup).