Choosing JavaScript's Var, Let or Const With Confidence

Understanding the difference between JavaScript var, let, and const keywords

JavaScript has so many ways to declare variables: var, let, const.

Which one to pick?

This post will clarify the differences between these JavaScript keywords. And once we understand the nuances between them, we’ll be on our way to making the right choice.

thumbs up response to learning the differences between JavaScript's 'let', 'var', and 'const' keywords

ES2015 (ES6) introduced let and const to the JavaScript language.

Before ES2015, var was the only keyword available for holding values.

Var

The var keyword, compared to let, and const, has the most flexibility.

It can be redeclared with a new value. Its value can also be updated.


To make sure that we're on the same page so far, let's illustrate this with an example.


If we declare:

var name = "Frank";

We can then redeclare:

var name = "Bob";

Now, if we want to update the value assigned to var name, we can do:

name = "Bobby";
JavaScript's 'var' keyword is flexible like a cat

Const

Now we can examine the const keyword, which is practically the polar opposite of the var keyword.

This is because, unlike var, a const can’t be redeclared nor can it be updated.


Let's take a look at an example.

If we declare:

const name = "Frank";

We're unable to redeclare const name:

const name = "Bob";

Doing so will result in a SyntaxError letting us know that Identifier ‘name’ has already been declared.


And an attempt to update the assignment of const name:

name = "Bobby";

will result in a TypeError Assignment to constant variable!

JavaScript's 'const' keyword is strict because it can't be redeclared or updated

One source of confusion is that the thing that is constant is the binding of the declared const to the value. It's not necessarily that the value itself becomes immutable.

When the value assigned is a primitive(string, number, boolean, null, undefined, or symbol), the value is immutable. However, when the value is an object, like an array, mutation of the value is possible.


To demonstrate the mutability of an object when declared as a const, we’ll first declare const colors as an Array:

const colors = [“blue”, “red”, “green”, “yellow”];

We can then push, for example, to this array without problem:

colors.push(“purple”);

Now the value of const colors is:

[“blue”, “red”, “green”, “yellow”, “purple”]

See, that array was mutable after all. 🙂


A good rule of thumb for const is to use const when we have data we do not expect to rebind. Not only does it help prevent accidental reassignment, but it also helps communicate our intent for both our future selves as well as others who may read our code.

Let

Now, the JavaScript let keyword falls in the middle of var and const in terms of flexibility. Because, unlike var, redeclaration is not possible. Like var, however, it is possible to update.


Let's look at let in the context of our previous examples.

If we declare:

let name = "Frank";

We're unable to redeclare let name:

let name = "Bob";

The result is a SyntaxError letting us know that Identifier ‘name’ has already been declared


Updating the assignment of let name, however, is valid:

name = "Bobby";

Scope

We’ve seen how binding works with var, let, and const.

Another big idea to discuss to help clarify the differences between these keywords is Scope.

Before ES2015, there were two kinds of scope: Global and Function.

Now, however, we have “Block Scope” as well.

Anytime we have curly brackets, as in an If statement, Block Scope is indicated. (Some other places to find Block Scope are with the For, While, and Do keywords).

The idea behind scope, in general, is that it lets us know where variables are available within our program.

So, a variable assigned within a function, for example, is said to be locally scoped to that particular function.

We can think of the curly brackets as a fence or prison walls within which it confines locally scoped variables.

The 'let' and 'const' keywords are block scoped. It's like they're behind prison walls because they can't be accessed from their outer environment.

Both const and let are block scoped. And the benefit of block scoping is that it prevents these variables from being accessible from their outer environment.

Usually, a var declared within a function is only accessible within that function.

Take the following function as an example:

function sayName() {
    var name = “Frank”;
    console.log(name);
}

If we then try to log name in the global scope, we get a ReferenceError: name is not defined. Here, we can say that var is function scoped.

Block scoping, however, is like a more specific level of scope.

Take this example:

function sayName() {
  var name = "Frank";
  {
    let color = "red";
  }
  console.log(name);
  console.log(color);
}

Although this example isn't too practical, it illustrates the point.

In this case, once we invoke sayName, we see “Frank” printed to the console.

However, we get a ReferenceError: color is not defined.

As we can see, since we used the let keyword when declaring color, color is block scoped.

Therefore, it's only available within the curly brackets in which it resides.