const vs let

Tim Kendrick May 17, 2016

TL;DR: Every time you’re about to write let, consider using const instead

ES6 brought with it two new block-scoped assignment keywords: let and const. The only difference between these two is that variables declared using let can be reassigned, whereas variables declared using const cannot:

let artistName = 'Prince';
artistName = 'The Artist Formerly Known As Prince'; // All fine

const immutableArtistName = 'Prince';
immutableArtistName = 'TAFKAP'; // TypeError: Assignment to constant variable

Most people, when moving to ES6, seem to replace all their var statements with let statements. While this enforces the much-needed block-scoping, I’d argue that almost all the time you should go one step further and replace them with const.

Why? I find that the immutability provided by un-reassignable variables generally makes debugging much simpler, produces code that is easier to reason about, and fits much better within the functional style of JavaScript that has become more popular due to libraries such as React and Redux.

The main gotcha to keep in mind while using const is that while the variable itself cannot be reassigned, the contents of its value is still mutable and can therefore be modified:

const artist = { name: 'Prince', birthName: 'Prince Rogers Nelson' };
artist.name = 'TAFKAP'; // No error thrown
console.log(artist); // Object {name: "TAFKAP", birthName: "Prince Rogers Nelson"}

…to maintain immutability, I’d advise introducing an additional rule whereby you never modify the contents of objects, instead creating a clone of the object with the updated properties:

const artist = { name: 'Prince', birthName: 'Prince Rogers Nelson' };
const updatedArtist = Object.assign({}, artist, { name: 'TAFKAP' });
console.log(artist); // Object {name: "Prince", birthName: "Prince Rogers Nelson"}
console.log(updatedArtist); // Object {name: "TAFKAP", birthName: "Prince Rogers Nelson"}

…or if you’re already using ECMAScript stage 2 features, you can use the object spread syntax to get rid of the ugly Object.assign call:

const artist = { name: 'Prince', birthName: 'Prince Rogers Nelson' };
const updatedArtist = { ...artist, name: 'TAFKAP' };
console.log(artist); // Object {name: "Prince", birthName: "Prince Rogers Nelson"}
console.log(updatedArtist); // Object {name: "TAFKAP", birthName: "Prince Rogers Nelson"}

…or alternatively use a library such as Immutable.js to ensure that your data objects remain unmodified.

The advantage of returning a clone of the object, rather than just modifying the original, is that you can ensure that your object never changes during the lifecycle of your program. This makes debugging much easier, and also allows you to verify much more efficiently whether an update will lead to changes in the application state (e.g. by using a single strict equality check in a React-style diff algorithm, rather than recursively iterating through all the object properties to determine whether something has updated).

In short, if you find that your code relies on reassigning variables declared with let or var, I’d suggest refactoring it such that it can be expressed purely with const assignments, so whoever reads your code will always know exactly what value each variable refers to.