DEV Community

Cover image for Demystifying "const" variables in JavaScript
Sunny Singh
Sunny Singh

Posted on • Originally published at sunnysingh.io

Demystifying "const" variables in JavaScript

By now, ES6 (ES2015) is widespread enough that many developers are writing their JavaScript with this modern syntax. However, I commonly see room for improvement with variable declarations. Specifically, when I see a let to declare an object that is updated, but never reassigned a new value.

Here is the offending example:

let cache = {};

cache.id = 'hello';

// We never reassign cache to a different value.
// It's a reference to the same object.
Enter fullscreen mode Exit fullscreen mode

Yes, that can actually be a const because the cache variable is never reassigned.

Immutability vs Reassignment

Many refer to const declarations as creating "immutable" variables. Immutable meaning that the value (including properties of objects) can never be updated.

If that is the case, then let's try our initial example using a const:

const cache = {};

cache.id = 'hello';

console.log(cache.id); // will output "hello"
Enter fullscreen mode Exit fullscreen mode

If cache is now an immutable, non-changeable constant, then attempting to add an id property to it will not work or even throw an error.

However, if you try running that example, it will work perfectly fine. The string "hello" will be logged, which is retrieved from the updated object.

Okay, so if const does not declare something as immutable, what does it do? Well, a const prevents a variable from being reassigned a new value.

Here are a few examples of reassigning variables:

let cache = {};

cache = { id: 'hello' }; // reassigning variable to a new object

let isSuccess = false;

isSuccess = true; // reassigning variable to false boolean
Enter fullscreen mode Exit fullscreen mode

Changing any of the above let statements to const instead will throw a type error: "Uncaught TypeError: Assignment to constant variable."

Setting a property on an object, or updating an existing property, is not reassignment. The value of the variable is still the same object, and you are updating the properties of that object.

Benefit of using const

Hopefully you understand how const and let differ now, but that probably still begs one major question: why should I care enough to use const?

It mainly comes down to the quality of your code, and how much information you or another developer can infer from it. For example, as I'm looking through one file in a codebase, I see this:

let isSuccess = true;
Enter fullscreen mode Exit fullscreen mode

Okay, so it's a variable that declares whether some operation succeeded or not, in this case it has since the value is true. However, the let also tells me that this variable can be reassigned to false anywhere later on in that file.

To double check, I search for all instances of isSuccess in the file. Hmm, it's not reassigned anywhere, so I know that this variable's value will remain true.

Sounds like a constant to me, and if this variable was actually declared as a const then I wouldn't have to search anywhere else in the file for it.

Now imagine you revisit this code a few months later. Way down in the file, you add this:

isSuccess = false;
Enter fullscreen mode Exit fullscreen mode

Uh oh, you potentially caused a bug just now because when you initially wrote this code for isSuccess to be true, you weren't expecting anyone to change it later on. Even your future self.

This is an extremely common scenario, especially in large codebases with multiple developers. The great part is that this is easily solved by using const and let appropriately.

Default to const, but use let when necessary

As a common rule, I suggest using const to declare all new variables, and when you come across a point where you need to reassign one of those variables, then change it to a let.

Here's a much bigger example of how you might use both properly:

const cache = {};
let user = {};
let isSuccess = false;

// The `cache` variable is never reassigned a new value.
cache.greeting = `Hello`;

// The `user` variable is not reassigned a new value right now.
user.id = 1;

// Here, we assign `user` and `isSuccess` new values.
user = {};
isSuccess = true;
Enter fullscreen mode Exit fullscreen mode

It's definitely a paradigm shift to declare variables with const instead of var and let, but it can add more confidence to your code. Try it out and let me know what you think.

Want to learn how to improve your code even further? You might like my Writing code for your future self article.

Top comments (21)

Collapse
 
cecilelebleu profile image
Cécile Lebleu

As a common rule, I suggest using const to declare all new variables, and when you come across a point where you need to reassign one of those variables, then change it to a let.

Great explanation! I will definitely be trying this, as I have always been confused about const and when to use it. But looking at it “upside down” is a great approach. Thanks!

Collapse
 
jckuhl profile image
Jonathan Kuhl

It's always been my rule of thumb.

Use const. If you need to reassign it, change the variable to let. No reason to use var anymore.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

One reason to use var: prototype something in the browser console and get something wrong, for that session your const won't be changeable, so use var for fast prototyping

Collapse
 
nickytonline profile image
Nick Taylor

I use const all the time. It's very rare that I need let. I can see let being used as an index in a for loop, but I almost never need a for loop. Filter, map and reduce usually do the trick.

Collapse
 
georgecoldham profile image
George

Functional and immutable Js makes code more readable and maintainable imo. I almost exclusively use const, I have yet to find a scenario where I need to change this.

Collapse
 
sunnysingh profile image
Sunny Singh

We're in the same boat! I try to avoid let and even loops, which people think I'm crazy for.

Collapse
 
georgecoldham profile image
George

Map, Filter and Reduce are loops, but they are immutable for the purpose of us devs.

Thread Thread
 
sunnysingh profile image
Sunny Singh

They're declarative loops, but yes definitely loops.

Collapse
 
karataev profile image
Eugene Karataev • Edited

Thanks for the post. I use const only for constants in top-level scope like const URL = 'https://example.com'.
For other scenarios I prefer to use let. It's just annoying to change const to let every time you need to make a variable mutable.

This post by TC39 committee member Jamie Kyle is rude, but resonates with my view on let vs const battle.

Collapse
 
sunnysingh profile image
Sunny Singh

Thanks for sharing that post.

I'm not sure I can fully agree with Kyle. Most of his points are fair, but the main goal of const is to communicate intention. Yes if I didn't reassign my variable, then I intend on it not to change. Later on when I come back and want to change it that's fine, I just know that it's not being changed currently so I can be more aware of that.

Collapse
 
johncip profile image
jmc • Edited

Agreed, that post misses the point.

Why am I not surprised that someone like that is on the language committee? (I'd say JS culture is basically worse is better, but somehow its movers and shakers manage to screw up even that up.)

Collapse
 
joeattardi profile image
Joe Attardi

To add to this - if you want your object to actually be immutable, you can use Object.freeze. If the object contains other objects, this will only freeze the first level of values. You can use the deep-freeze package to recursively freeze the object.

Collapse
 
johncip profile image
jmc • Edited

Agreed, defaulting to const is useful if because then when you see a let you know it must get reassigned.

More generally, sometimes variables are "values," and sometimes they're "places," and to me it's worth an extra two characters to be clear about which I'm using.

It's not about avoiding any sort of actual risk -- just about writing code that better expresses its intent.

Collapse
 
ceceliacreates profile image
Cecelia Martinez

Great article! My boot camp instructor also advocates a "const first" approach, for all the reasons you outlined here. I'd rather get a "reassignment to a constant variable" error, which is easily identified and fixed, then trying to figure out why my code is broken due to an inadvertent reassignment.

Collapse
 
latheresienne profile image
Latheresienne

Overcome imposter syndrome on this topic. Thank you ! Great article !

Collapse
 
sunnysingh profile image
Sunny Singh

Awesome to hear 😁

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

99% of the time your variable reference won't need to change (reassigned) so use const, for the other use let, it's that simple.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Do you like constant case?

Collapse
 
johncip profile image
jmc • Edited

Not OP, but I mentally distinguish between "values," which use const but tend to be local / temporary, and "constants," which also use const but tend to be in outer scope. I use screaming snake case only for the latter, if at all.

IMO when most of your values are immutable, which is a good place to be, the constants stop being special. Instead, the the things that can change over time are special, as they should be, since they require more effort to reason about.

Collapse
 
sunnysingh profile image
Sunny Singh • Edited

I do, for real constants that are static values. Consider this example:

const BASE_URL = 'http://example.com';

const url = `${BASE_URL}/hello`;

Since url isn't a true constant (it uses another variable to determine its value), I keep it lowercase.

Also, I only use constant case at the top level scope, or when I'm importing constants from another file.

Collapse
 
shubhambattoo profile image
Shubham Battoo • Edited

People overuse let a lot, it feels like var to them so keep using it, really nicely pointed out.