ES6 in Action: let and const

Share this article

ES6 let and const

Key Takeaways

  • ES6 introduces two new keywords, ‘let’ and ‘const’, which provide a way to define block-scope variables and constants, enhancing JavaScript’s functionality and reducing potential errors.
  • The ‘let’ keyword allows for the declaration of variables within a specific block scope, which is a significant shift from JavaScript’s previous limitation to function and global scopes. Variables declared with ‘let’ are not hoisted, meaning they can’t be referenced before their declaration within the block.
  • The ‘const’ keyword is used to define constants that can’t be redeclared. While ‘const’ creates an immutable binding, it doesn’t make the value itself immutable. To achieve value immutability, one should use Object.freeze(). Both ‘let’ and ‘const’ are supported in Node and all modern browsers.

In this tutorial, I’ll introduce let and const, two new keywords added to JavaScript with the arrival of ES6. They enhance JavaScript by providing a way to define block-scope variables and constants.

This article is one of many covering new features of JavaScript introduced with ES6, including Map and WeakMap, Set and WeakSet, new methods available for String, Number, and Array, and the new syntax available for functions.

let

Up to ES5, JavaScript had only two types of scope, function scope and global scope. This caused a lot of frustration and unexpected behaviors for developers coming from other languages such as C, C++ or Java. JavaScript lacked block scope, meaning that a variable is only accessible within the block in which it’s defined. A block is everything inside an opening and closing curly bracket. Let’s take a look at the following example:

function foo() {
  var par = 1;
  if (par >= 0) {
    var bar = 2;
    console.log(par); // prints 1
    console.log(bar); // prints 2
  }
  console.log(par); // prints 1
  console.log(bar); // prints 2
}
foo();

After running this code, you’ll see the following output in the console:

1
2
1
2

What most developers coming from the languages mentioned above would expect, is that outside the if block you can’t access the bar variable. For example, running the equivalent code in C results in the error 'bar' undeclared at line ... which refers to the use of bar outside the if.

This situation changed in ES6 with the availability of block scope. The ECMA organization members knew that they could not change the behavior of the keyword var, as that would break backward compatibility. So they decided to introduce a new keyword called let. The latter can be used to define variables limiting their scope to the block in which they are declared. In addition, unlike var, variables declared using let aren’t hoisted. If you reference a variable in a block before the let declaration for that variable is encountered, this results in a ReferenceError. But what does this mean in practice? Is it only good for newbies? Not at all!

To explain you why you’ll love let, consider the following code taken from my article 5 More JavaScript Interview Exercises:

var nodes = document.getElementsByTagName('button');
for (var i = 0; i < nodes.length; i++) {
  nodes[i].addEventListener('click', function() {
    console.log('You clicked element #' + i);
  });
}

Here you can recognize a well-known issue that comes from variable declaration, their scope, and event handlers. If you don’t know what I’m talking about, go check the article I mentioned and than come back.

Thanks to ES6, we can easily solve this issue by declaring the i variable in the for loop using let:

var nodes = document.getElementsByTagName('button');
for (let i = 0; i < nodes.length; i++) {
  nodes[i].addEventListener('click', function() {
    console.log('You clicked element #' + i);
  });
}

The let statement is supported in Node and all modern browsers. There are, however, a couple of gotchas in Internet Explorer 11 which you can read about in the ES6 compatability table.

A live demo that shows the difference between var and let is shown below and is also available at JSBin:

const

const addresses the common need of developers to associate a mnemonic name with a given value such that the value can’t be changed (or in simpler terms, define a constant). For example, if you’re working with math formulas, you may need to create a Math object. Inside this object you want to associate the values of π and e with a mnemonic name. const allows you to achieve this goal. Using it you can create a constant that can be global or local to the function in which it is declared.

Constants defined with const follow the same scope rules as variables, but they can’t be redeclared. Constants also share a feature with variables declared using let in that they are block-scoped instead of function-scoped (and thus they’re not hoisted). In case you try to access a constant before it’s declared, you’ll receive a ReferenceError. If you try to assign a different value to a variable declared with const, you’ll receive a TypeError.

Please note, however, that const is not about immutability. As Mathias Bynens states in his blog post ES2015 const is not about immutability, const creates an immutable binding, but does not indicate that a value is immutable, as the following code demonstrates:

const foo = {};
foo.bar = 42;
console.log(foo.bar);
// → 42

If you want to make an object’s values truly immutable, use Object.freeze().

Browser support for const is equally good as for let. The statement const is supported in Node and all modern browsers. But here, too, there are some gotchas in Internet Explorer 11, which you can read about in the ES6 compatability table.

An example useage of const is shown below:

'use strict';

function foo() {
  const con1 = 3.141;
  if (con1 > 3) {
    const con2 = 1.414;
    console.log(con1); // prints 3.141
    console.log(con2); // prints 1.414
  }
  console.log(con1); // prints 3.141
  try {
    console.log(con2);
  } catch(ex) {
    console.log('Cannot access con2 outside its block');
  }
}
foo();

A live demo of the previous code is shown below and also available at JSBin.

Conclusion

In this tutorial, I’ve introduced you to let and const, two new methods for declaring variables that were introduced to the language with ES6. While var isn’t going away any time soon, I’d encourage you to use const and let whenever possible to reduce your code’s susceptibility to errors. By way of further reading, you might also like our quick tip How to Declare Variables in JavaScript, which delves further into the mechanics of variable declaration.

Frequently Asked Questions (FAQs) about ES6 Let and Const

What is the difference between var, let, and const in JavaScript ES6?

In JavaScript ES6, var, let, and const are used to declare variables. The key difference between them lies in their scope and reassignment. Var is function-scoped, meaning it’s only available within the function it’s declared in. On the other hand, let and const are block-scoped, meaning they’re only available within the block they’re declared in. As for reassignment, variables declared with var and let can be reassigned, while those declared with const cannot. This makes const ideal for values that should remain constant throughout the program.

When should I use let and const in my code?

You should use let when you need to declare a variable that will change over time, such as a counter in a loop, or a value swap in an algorithm. Const should be used when you have a value that you know won’t change, like a configuration setting or a reference to a DOM element. Using const can make your code easier to read and understand, as it signals to other developers that the value should not be changed.

Can I reassign a const variable in JavaScript ES6?

No, you cannot reassign a const variable in JavaScript ES6. Once a const variable has been assigned, trying to reassign it will result in a TypeError. However, if the const variable is an object, you can change the properties of the object, but you cannot change the object itself.

What is the scope of a let variable in JavaScript ES6?

In JavaScript ES6, a let variable has block scope. This means it is only accessible within the block of code in which it is defined. If you try to access it outside of this block, you will get a ReferenceError.

What happens if I declare a variable with let or const without initializing it?

If you declare a variable with let or const without initializing it, it will be undefined. However, unlike var, you cannot use a let or const variable before it is declared. Doing so will result in a ReferenceError.

Can I declare a variable with the same name using let or const in the same scope?

No, you cannot declare a variable with the same name using let or const in the same scope. Doing so will result in a SyntaxError. This is known as the Temporal Dead Zone rule.

What is hoisting in the context of let and const?

Hoisting is a JavaScript mechanism where variables and function declarations are moved to the top of their containing scope during the compile phase. However, unlike var, let and const declarations are not initialized. They are hoisted but you cannot access them before the declaration, as they are in a “temporal dead zone” from the start of the block until the declaration is processed.

Can I use let and const in all browsers?

Let and const are part of the ES6 (ES2015) specification and are supported in all modern browsers. However, for older browsers that do not support ES6, you would need to use a transpiler like Babel to convert your ES6 code into ES5 code.

What is the performance impact of using let and const?

The performance impact of using let and const is negligible. The JavaScript engine optimizes for these keywords, so there is no significant performance difference between them and var. The choice between let, const, and var should be based on their scoping rules and reassignment behavior, not performance.

What are some best practices for using let and const in JavaScript ES6?

Some best practices for using let and const in JavaScript ES6 include using const by default, and only using let when you know a variable needs to change. This can make your code more predictable and easier to understand. Also, always declare variables at the top of their scope, to make it clear where they are available.

Aurelio De RosaAurelio De Rosa
View Author

I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.

ColinIECMAScript6harmonylearn-modernjsmodernjsmodernjs-hubvariables
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week