Why can I change a constant object in javascript
Solution 1
The documentation states:
...constant cannot change through re-assignment
...constant cannot be re-declared
When you're adding to an array or object you're not re-assigning or re-declaring the constant, it's already declared and assigned, you're just adding to the "list" that the constant points to.
So this works fine:
const x = {};
x.foo = 'bar';
console.log(x); // {foo : 'bar'}
x.foo = 'bar2';
console.log(x); // {foo : 'bar2'}
and this:
const y = [];
y.push('foo');
console.log(y); // ['foo']
y.unshift("foo2");
console.log(y); // ['foo2', 'foo']
y.pop();
console.log(y); // ['foo2']
but neither of these:
const x = {};
x = {foo: 'bar'}; // error - re-assigning
const y = ['foo'];
const y = ['bar']; // error - re-declaring
const foo = 'bar';
foo = 'bar2'; // error - can not re-assign
var foo = 'bar3'; // error - already declared
function foo() {}; // error - already declared
Solution 2
This happens because your constant is actually storing a reference to the array. When you join something into your array you are not modifying your constant value, but the array it points to. The same would happen if you assigned an object to a constant and tried to modify any property of it.
If you want to freeze an array or object so it can't be modified, you can use the Object.freeze
method, which is already part of ECMAScript 5.
const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]
Solution 3
Came through this article while searching on why I was able to update an Object even after defining it as const
. So the point here is that it is not the Object directly but the attributes it contains which can be updated.
For example, my Object looks like:
const number = {
id:5,
name:'Bob'
};
The above answers correctly pointed out that it's the Object which is const and not its attribute. Hence, I will be able to update the id or name by doing:
number.name = 'John';
But, I will not be able to update the Object itself like:
number = {
id:5,
name:'John'
};
TypeError: Assignment to constant variable.
Solution 4
This is consistent behavior with every programming language I can think of.
Consider C - arrays are just glorified pointers. A constant array only means that the value of the pointer will not change - but in fact the data contained at that address is free to.
In javascript, you are allowed to call methods of constant objects (of course - otherwise constant objects would not serve much purpose!) These methods might have the side effect of modifying the object. Since arrays in javascript are objects, this behavior applies to them as well.
All you are assured of is that the constant will always point to the same object. The properties of the object itself are free to change.
Solution 5
The keyword const is a little misleading.
It does not define a constant value. It defines a constant reference to a value.
Because of this you can NOT:
- Reassign a constant value
- Reassign a constant array
- Reassign a constant object
But you CAN:
- Change a constant array
- Change a constant object
Related videos on Youtube
Salvador Dali
I am a Software Engineer in the Google Search Growth team. I use Tensorflow and TFX to analyze search data and Go to write data pipelines. This is my personal profile which has absolutely nothing to do with my employer.
Updated on July 25, 2022Comments
-
Salvador Dali almost 2 years
I know that ES6 is not standardized yet, but a lot of browsers currently support
const
keyword in JS.In spec, it is written that:
The value of a constant cannot change through re-assignment, and a constant cannot be re-declared. Because of this, although it is possible to declare a constant without initializing it, it would be useless to do so.
and when I do something like this:
const xxx = 6; xxx = 999; xxx++; const yyy = []; yyy = 'string'; yyy = [15, 'a'];
I see that everything is ok
xxx
is still6
andyyy
is[]
.But if I do
yyy.push(6); yyy.push(1);
, my constant array has been changed. Right now it is[6, 1]
and by the way I still can not change it withyyy = 1;
.I this a bug, or am I missing something? I tried it in the latest chrome and FF29
-
Andrew about 10 yearsCan you just create a class, declare the variable and assign its value inside the class. Then, create a GETTER for that variable; and do not implement a setter. It should implement a constant...
-
Salvador Dali about 10 years@Andrew thanks, but I am not asking how can I do this. I am curious why const keyword behaves this way.
-
-
Salvador Dali about 10 yearsso you mean that this is not a bug, but it should work this way? Because I thought that idea of the constant is that it can not be changed. Basically a programmer has trust that no matter what will happen, nothing can change the value inside of my constant.
-
veritas about 10 yearsI think it's not so easy, in this case the value of the constant is an array of specific elements. Changing anything means that you change the value.
-
adeneo about 10 yearsYes, it's supposed to work this way, you're not re-assigning the constant, it's still the same reference, you're just adding to the array the constant references, and arrays and objects are like "lists", modifying them does not change the reference or re-declare the constant.
-
Matt Burland about 10 years@SalvadorDali: constant and read-only are two different things. Your variable is constant, but the array it's pointing to isn't read-only
-
Ashith almost 6 yearsBy that same logic, a constant
five
set to 5 doesn't actually have a value of 5, it is just a reference to the number 5. So if I dofive++
I'm not changing the constant, just the number it points to. -
Guilherme Sehn almost 6 years@Anthony the reference thing only works for arrays and objects, not primitive values
-
sidgeon smythe about 5 years@Anthony In your example, you're changing the number that the variable
five
points to (the variablefive
used to be a label for the number 5, now it's pointing to a different number: 6). In the example in the question (and this answer),x
always points to the same list; ifx
is const you cannot make it point to a different list. The only difference is that the same list can grow or shrink; this is something only possible for arrays and objects and not for primitives. -
Ebrahim over 4 yearsyour example is a practical one and correct descriptions
-
user1063287 over 2 yearshere is another beginner-friendly explanation of how primitive types and objects are saved in memory and their subsequently different behaviour (from 2017 so slightly dated, but a pretty good introduction to the topic): youtube.com/watch?v=9ooYYRLdg_g
-
Programmer Dancuk over 2 yearsthank you on this. It clarifies how const works in JS that damn cumbersome compared to other langs especially statically typed language.
-
user137369 about 2 yearsSwift is an example of a language which does not work like this.
let someArray = ["one"]; someArray.append("two")
fails to compile witherror: cannot use mutating member on immutable value: 'someArray' is a 'let' constant
andnote: change 'let' to 'var' to make it mutable
. -
Teekin about 2 yearsExplaining why I'm downvoting. There's an obvious reason why this is being asked; because it's contrary to what programmers are used to. Constants in C/C++ are typically defined by an immutable macro, in PHP by a specific
define()
function. When programmers say "constant", they typically mean "something that will not change", nevermind the mathetmatics under the hood. That's why ONLY IN JAVASCRIPT people are consistently confused by this bizarre choice of keyword use; because it's a bad one. The answer here isn't technically incorrect per se, it's just also not very useful. -
Teekin about 2 yearsUpvoting for pointing out that the keyword is misleading. It is.
-
Nick Rolando about 2 yearsSo basically the variable is a pointer, and as
const
you cannot change the memory address it is referencing or pointing to, but you're free to change the value that memory address is holding?