This post is part of learning ES6 series.

Let's look at the differences  between  var, let, and const in ES6 today. var, let, and const  are different ways of declaring variables in JavaScript. var has been around since the beginning, and let and const were introduced recently in 2015.


VAR

In order to understand what benefits let and 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

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

With var you can be a magician and use a variable before it even exists.

Now, lets see how let and const address these problems.


LET

Re-declaration

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 let inside of the if block to var to see what the compiler does. Will it throw an error message or will it work (silently)?

Scoping

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:

By using 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

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.

If a 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 const whose binding and internal state is truly immutable, you can use Object.freeze() to achieve this outcome.

CONCLUSION

In summary, let and const are a safer (and IMHO a better) way to declare variables in JavaScript. Before let and  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 let and const.

I like (and recommend) Mathias's approach to using var , const, and 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).