I code using const (and why you should too)
Tags: javascript, const, let, programming
Published: 2020-04-03 16:23:56

There have been endless tweets and many blog posts (even this [expletive-laden rant](https://jamie.build/const)) 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.

```js
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.

```js
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](https://en.wikipedia.org/wiki/Code_smell)". It's verbose, repetitive, and adds visual clutter.

Let's try it again using a `const` instead.

```js
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`.

```js
const myCar = perferSportsCar ? sportsCar : minivan;
```

Here we decide on a value using a [ternary](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) 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.

```js
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.

```js
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.

```js
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](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/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! 💃