Why do we ‘prefer-const’

David Buchan-Swanson
Tanda Product Team
Published in
2 min readJan 9, 2018

At Tanda, on all of our newer projects, we use a fairly strict ESLint config. This is largely due to the fact that I’m a bit of a tooling nerd, and also because I like the consistency they bring to the codebase.

One of the rules we use almost everywhere is prefer-const . This rule seems like second nature to me now. But, it’s not (well, wasn’t) enabled on our main codebase. This is mostly due to oversight, and the fact we’ve only recently moved to a compiled JavaScript architecture.

Today, in a pull request, a developer used let for a value that was never re-assigned to. I overheard another developer asking about a concrete example of why we should use const over let, even though it seemed better. The following is the example I came up with. Its a little trivial, but the people who read it internally seemed able to extrapolate it out into something they could see happening.

Also, before we start, const in JavaScript doesn’t mean immutable. It means ‘the reference that this variable points is immutable’. You just can’t re-assign it. You can still push to arrays and modify objects declared with const, so you only ever need let if you’re doing let i = 0; i = 1 -style re-assignments.

So, say you write a function that uses some variable you’ve declared in an outer scope (for some reason).

Now, I wouldn’t recommend tying the safety of your production database to code in this way, but, it’s happened.

You write some unit tests that all pass.

In two months time, someone else comes along and they write another function. It’s in the same file as your other one, but it’s in a very different spot (it’s a really big file).

They’ve forgotten an identifier for their variable. This is perfectly legal JS, even if your let variable was not there. It just declares it as a global variable (that’s not great, but it happens). Unit tests are written, and they all pass. Because your code hasn’t changed, and the unit tests all run independently, yours still pass, too.

Now, someone uses the doSomething function and it executes before your code runs. It sets myVar to 3 (maybe 4 ), and then your function runs some time later and deletes the production database. Whoops.

Now, if you change that let to a const, you’ll instead get a compile-time error if you are transpiling your code, or you’ll get a TypeError at run-time if you run it directly in a modern browser. Either way, you’ve saved production, and only added 2 bytes (0 if you transpile — const and let both transpile to var).

--

--