Const and Let Variables Explained

If you’ve worked with JavaScript at all you’ve undoubtedly used the var keyword to define variables, but there’s now other ways to define variables too: let and const.

First let’s do a quick review of var. Two of the key properties of variables defined with var are that:

1) They are scoped to the function in which they are declared, or if there is no function, the global/window frame.

2) They are hoisted at compile time, meaning that they are allocated in memory as soon as the script loads.

Here’s an example:

console.log("before the block myVar equals " + myVar);
if (1 < 2){
  var myVar = "inside an if block";
  console.log("inside the block myVar equals " + myVar);

}
console.log("after the if block myVar equals " + myVar);

Output:

"before the block myVar equals undefined"
"inside the block myVar equals inside an if block"
"after the if block myVar equals inside an if block"

Variables defined with let

You can also define variables using the keyword let instead of var. Here’s how let variables differ from var:

1) Thy are scoped to the block in which they are declared. In addition to functions, this includes things like if statements and while/for loops.

2) They are not hoisted meaning that they do not exist in memory in any way until the interpreter gets to the line on which they are defined.

Let’s look at what happens if you swap out var myVar with let myLet in the code from above:

console.log("before the block myLet equals " + myLet);
if (1 < 2){
    let myLet = "inside an if block";
    console.log("inside the block myLet equals " + myLet);
}
console.log("after the if block myLet equals " + myLet);

Output:

   ReferenceError: myLet is not defined

Because let variables are not hoisted, the code chunk error-ed on the first line and will not continue.

Let’s skip that first line though and see what we get:

if (1 < 2){
    let myLet = "inside an if block";
    console.log("inside the block myLet equals " + myLet);
}
console.log("after the if block myLet equals " + myLet);

Output:

"inside the block myLet equals inside an if block"
ReferenceError: myLet is not defined

Another error, but this time it’s after the if block has ended. As you can see, the myLet only existed in the if block. Unlike a var variable, it doesn’t exist in any form outside of this block.

In the right circumstances, let has several advantages over var, such as performance. Because let variables are cleaned up after their block completes, they’re no longer sitting around taking up memory. They’re also great for temporary variables such as in loops, and allow for cleaner code.

Consider the following:

var array = [1,2,3];

for (var i = 0; i < array.length; i += 1) {
  console.log(array[i]);
}
console.log("i is still equal to " + i);

Output:

"1"
"2"
"3"
"i is still equal to 3"

We don’t think about it, but i is still there in memory after the loop completes, taking up space, and possibly colluding with other loops. If we define i with let instead, it will be cleaned up as soon as the loop is over:

var array = [1,2,3];

for (let i = 0; i < array.length; i += 1) {
  console.log(array[i]);
}

console.log("i is now " + i);

Output:

"1"
"2"
"3"
ReferenceError: i is not defined

Variables defined with const

Variables defined with const are very similar to let variables.

1) Just like let, they are scoped to the block in which they are declared. In addition to functions, this includes things like if statements and while/for loops.

2) Just like let, they are not hoisted meaning that they do not exist in memory in any way until the interpreter gets to the line on which they are defined.

3) Variables defined with const will throw an error if you attempt to re- define them.

Here’s const in action:

const name = "Ralph";
console.log("In the global frame the name is " + name);
if (1 < 2){
  const name = "Sam";
  console.log("In this block name is " + name);
}
console.log("Back in the global frame the name is " + name);
const name = "Another name";

Output:

SyntaxError: Identifier 'name' has already been declared

As you can see, because we attempted to redefined name in the global namespace, it gave us an error.

Summary

Type Scope Hoisting Other
var function hoisted N/A
let block not hoisted N/A
const block not hoisted error if re-defined

So there you have it. As always the MDN pages on both let and const are great place to go for more information.