DEV Community

loading...
Cover image for "Variables declared with const cannot change" ... well kinda...

"Variables declared with const cannot change" ... well kinda...

beaufortaustin profile image Austin Beaufort ・2 min read

You've heard it 100 times...

let is mutable
const is immutable (not mutable)

well... sort of ...

The easy part to clear up is this:
** let is mutable **

If we declare a variable using let, we can re-assign that variable:

let myName = 'Tyler';
myName = 'John';
Enter fullscreen mode Exit fullscreen mode

this works just fine.

Now on to the confusing bit. (ha, no computer science pun intended.)

Basic types with const are immutable.
Examples of this:

const myName = 'Tyler';
myName = 'John'; // this line will throw an error

const myNumber = 7;
myNumber = 3; // this line will throw an error
Enter fullscreen mode Exit fullscreen mode

We cannot re-assign a string or number declared with const.

... "BuT WhaT AbOuT ObJectS AnD ArRaYS???" ...

good point. Check this out:

const employee = {
    id: 12345,
    name: 'John Doe',
    address: {
        street: '123 Circle St.',
        city: 'Pittsburgh',
        zip: 11111,
    }
}

employee.id = 99999,
employee.address = {}

console.log(employee) // { id: 99999, address: {} }
Enter fullscreen mode Exit fullscreen mode

We used const, but we can still change the inside values of the object itself. We even deleted a key/value pair entirely!

The same happens with Arrays:

const employee = [99999, 'John Doe', ['Cleveland', '123 Circle Street', 11111]]

employee.pop()
employee.pop()

console.log(employee) // [ 99999 ]
Enter fullscreen mode Exit fullscreen mode

Again, we used const, but we could still manipulate the inside values of the array.

This being said, we cannot re-assign the entire employee object or array, the following examples will result in an error:

const employee = [99999, 'John Doe', ['Cleveland', '123 Circle Street', 11111]]

employee = [4444, 'Jane Doe']

console.log(employee) // Error, cannot re-assign const


// example 2
const employee = {
    id: 12345,
    name: 'John Doe',
    address: {
        street: '123 Circle St.',
        city: 'Pittsburgh',
        zip: 11111,
    }
}

employee = {}

console.log(employee) // Error, cannot re-assign const
Enter fullscreen mode Exit fullscreen mode

So we have learned that we can change the insides of an object and array even though it was declared with const.

How do we stop this from happening?

One solution is to use Object.freeze().
This will work for objects and arrays that are not nested.

If an object or array is nested, the nested elements will still be able to be changed.

To "deep freeze" an object or array, we would need to create our own deep freeze function or use an external library.

Thanks for reading, for more tech content you can find me here:
Youtube => https://www.youtube.com/austinbeaufort
Twitter => https://twitter.com/AustinBeaufort

Discussion

pic
Editor guide
Collapse
dcwither profile image
Devin Witherspoon

Hey, thanks for sharing! BTW, you can tag code blocks with a language for better highlighting with adding js after your first 3 backticks .

Collapse
beaufortaustin profile image
Austin Beaufort Author

Hi Devin, Thanks for the tip, I just added the js code block tag to this article and the highlighting looks so much better!

Collapse
sleeplessbyte profile image
Derk-Jan Karrenbeld

Hi there Austin,

I saw on Twitter that you may think that this behaviour is special for Arrays or Objects (as in, it's a quirk) and I think that might be caused by the common confusion of what const actually means. Let me write out what I mean:

  • Primitives in JavaScript are always immutable, regardless of the const, var or let declaration.
  • Non-primitives are always mutable when they're created. It's possible to define properties that are not configurable (changable / deletable) or writable, and it's possible to force all properties to be non-configurable and non-writable, (including the __proto__ property) and prevent new properties from being defined via Object.freeze. You can use Object.seal if you to disallow removing/adding new properties, but still allow writing to those properties.

Okay great. So what?

const only says something about the variable binding. It only means that you won't be able to re-assign something to the binding, and says nothing about the value that's bound. This behaviour is the same between primitives and non-primitives:

const hello = 32
hello = 42
// => TypeError: Assignment to constant variable.

const goodbye = [32]
goodbye = [42]
// => TypeError: Assignment to constant variable.
Enter fullscreen mode Exit fullscreen mode

You can indeed change the goodbye value by not re-assigning it:

goodbye[0] = 42
Enter fullscreen mode Exit fullscreen mode

but that behaviour has nothing to do with const (or let, or var).

You won't be able to demonstrate the same with say... a number, because numbers are primitives, and can never be changed. There are no methods on numbers to mutate them, just like there are no methods on the other primitives, so it's hard to show equivalence.

I hope this makes sense, but please feel free to ask more if you want to know more!