DEV Community

loading...
Cover image for I code using const (and why you should too)

I code using const (and why you should too)

Donavon West
・4 min read

There have been endless tweets and many blog posts (even this expletive-laden rant) about how const really isn't constant or how "It's just compiled down to let by Babel anyway, so why use it?"

I'm here to tell you why I ignore all of this "sound advice" and rely on const as an indication of code quality.

Myth: const isn't constant

The fact is you can never re-assign a const. The value that's assigned to it will remain that value until the variable loses scope and is destroyed ('til death do us part?)

Let's take a look.

const myCar = carA;
myCar = carB;

VM101:1 Uncaught TypeError: Assignment to constant variable.

In the example above, you see that you can not, re-assign myCar. If you do, you get an exception.

Selectively assign a value to a const

Hold on. If a const is, um… constant, then how in the world can you selective assign it a value?

Let's look at some code that sets a variable based on some user preference.

let myCar;
if (perferSportsCar) {
  myCar = sportsCar;
} else {
  myCar = minivan;
}

The code above is something that you might find in many a source code repo today. Some people point to this as a valid use case for using let over const. I see it as "code smell". It's verbose, repetitive, and adds visual clutter.

Let's try it again using a const instead.

VM101:1 Uncaught TypeError: Assignment to constant variable.

Yeah, we all should have seen that coming.

How then can we use a const and what was all that talk about code smell?

When I see a let, it tells me that maybe there is a better way to express what you are trying to accomplish. Let's refactor the code to allow for a const.

const myCar = perferSportsCar ? sportsCar : minivan;

Here we decide on a value using a ternary and then assign it. The value of myCar is never re-assigned, but its initial value is selectively determined.

What if we can't use a simple ternary?

There are times when a simple ternary won't cut it. Take this common scenario.

let myCar;
if (type === 'sportscar') {
  myCar = sportsCar;
} else if (type === 'minivan') {
  myCar = minivan;
} else if (type === 'suv') {
  myCar = suv;
} else if (type === 'luxury') {
  myCar = luxury;
} else {
  myCar = economy;
}

Based on type we assign myCar to one of four different cars and default to economy if it's not one of the tested conditions.

When I'm doing a code review and something like this and see that let, it's a red flag. 🚩

Here's something a little more maintainable.

const cars = { sportscar, minivan, suv, luxury };
const myCar = cars[type] || economy;

What do you know, it can be expressed using a const (but you knew I was going to say that, didn't you?)

Are there exceptions to this? Certainly. Just the other day I wrote some code that set the value of a let based on a range of numeric values. This would have been more difficult, and make the code less maintainable if I had used a const.

If const is constant, then why can I change its value?

If your const contains an array or an object, yes, you can change its properties, but the value remains constant. Take this example.

const sportsCar = new Car({type: 'sportscar'});
const myCar = sportsCar;

myCar === sportsCar; // true

myCar.color = 'red';
myCar === sportsCar; // true

Notice that we've changed (i.e. mutated) myCar by setting the color property to "red", yet its value (i.e. sportsCar) remains the same.

Think of it like this. If I buy a car and then paint it red. Is it the same car? Yes. What if I install some sweet new rims? It's still the same car. Starting to get the picture?

Simply changing some aspect of my car doesn't make it a different car, just like setting myCar.color='red' doesn't change the value myCar.

Note: There are ways to freeze an object, which prevents mutation, but that's a different story.

In conclusion

Show me a project coded using all const and I'll show you one that is in all likelihood well written.

For me, const vs. let is less about re-assignment and more about what it says about your code. If your code can be written with all const then I get a better feeling that nothing fishy 🐠 is going on. And when I see that one let, it tells me that I need to examine what's going on a little further.

So let (pun intended) Babel changes my const's to let's a transpile time. As many proponents of let are quick to point out, we save one character per instance in our bundle size! 💃

Discussion (0)