Constant Variables in JavaScript, or: When "const" Isn't Constant

ECMAScript 2015 introduced the let and const keywords as alternatives to var, which JavaScript has always had. Both let and const declare local variables with block scope rather than function scope. In addition, const provides some notion of constancy, which let doesn't.

Unfortunately, the name of the const keyword might be misleading. In JavaScript, const does not mean constant, but one-time assignment. It's a subtle yet important distinction. Let's see what one-time assignment means:

// We're declaring `PI` to be a constant variable.
const PI = 3.141592653589793;

// Any attempt to assign a new value to `PI`
// fails because `PI` is a constant variable.
PI = 0;
PI++;

// All of the variable declarations below fail
// because we can't declare a new variable with the
// same identifier as an existing constant variable.
var PI = 0;
let PI = 0;
const PI = 0;

However, variables declared using the const keyword do not generally have a truly immutable value. Remember, const does not mean "constant", it means one-time assignment. The part that's constant is the reference to an object stored within the constant variable, not the object itself. The following example illustrates the difference:

// We're declaring a constant variable
// to hold a settings object.
const settings = {
    baseUrl: "https://example.com"
};

// Since `settings` is a constant variable,
// an attempt to assign a new value will fail.
settings = {};

// However, the object is **not** immutable.
// This means we can change its properties!
settings.baseUrl = "https://evil.example.com";

Declaring a variable to be constant doesn't make the objects it references immutable, as the above example shows. Object properties can change or be deleted altogether. The same goes for arrays assigned to a constant variable; Elements can be added, removed, reordered, or modified:

const numbers = [1, 2, 3];
numbers.push(4);
numbers.shift();

// numbers = [2, 3, 4]

For the sake of completeness, it is possible to create true constants in some cases. If a primitive value (such as a string, number, or boolean value) is assigned to a constant variable, that variable will be a true constant. Our PI constant is an example for this. There's no way to modify the value of the numeric literal 3.141592653589793 after it has been assigned.

To make an object truly immutable, you can pass it to the Object.freeze function to prevent any changes to its properties. Be aware that freeze is shallow, so you'll have to recursively call it for nested objects if you want the entire object tree to be frozen. If you need immutable data structures, it might be safer and more convenient to use a library such as Facebook's Immutable.js which is specifically made for this purpose.

Use the coupon code LAUNCHDAY for $10 off!

Learn React

10 Comments

Sam

You can also make the object immutable with Object.freeze().

Jaime

Hi Marius! ^_^ Good post!

I think you are confusing the terms "lexical scoping" and "block scoping".

Lexical scoping describes how the JavaScript runtime resolves variables when you reference them in your code. It is described in depth in this chapter of YDKJS and referenced in ECMA262 as Lexical Environments. It basically consists on looking if there's a variable defined in the current scope and if not looking in the outer environment and so on.

In your article you meant "block scoping" instead of "lexical scoping", as in, declaring a variable scoped to a block of code.

kalin

Thanks for this, I was wondering a lot reading code using const in strange ways assuming const is a constant. Honestly, it's weird thing, I'm not sure I like it, but anyway - thanks again for explaining!

Brook Monroe

I'd prefer if const meant "constant" for everything, not just the JS equivalent of PODs. I guess there will still need to be some developer discipline in this area--but that's never a bad thing, right?

Brook Monroe

Also, can someone fix this CAPTCHA math widget? It looks like it's saying "70x06" (420) instead of "7x6" (42). Is   really necessary? Chrome echoes that as a rectangular box instead of a space.

Francis Kim

Yet to try immutable.js in my code - didn't know it was by Facebook though. Great post!

Usama Ahmed

After the birth of ES6 i found many javascript guys using const almost everywhere. I have a question do you consider below lines correct as in usage of const.

const ink = jade.renderFile('/views/email-password.jade',options); const $ = cheerio.load(link); const converted = inker.releaseTheKraken($); const inclined = juice(converted.html());