210

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 still 6 and yyy 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 with yyy = 1;.

Is this a bug, or am I missing something? I tried it in the latest chrome and FF29

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Salvador Dali
  • 214,103
  • 147
  • 703
  • 753
  • 1
    Can 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... – Andrew May 02 '14 at 20:42
  • 18
    @Andrew thanks, but I am not asking how can I do this. I am curious why const keyword behaves this way. – Salvador Dali May 02 '14 at 20:45

13 Answers13

304

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
user1063287
  • 10,265
  • 25
  • 122
  • 218
adeneo
  • 312,895
  • 29
  • 395
  • 388
  • 19
    so 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. – Salvador Dali May 02 '14 at 20:39
  • 2
    I 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*. – veritas May 02 '14 at 20:42
  • 9
    Yes, 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. – adeneo May 02 '14 at 20:44
  • 52
    @SalvadorDali: *constant* and *read-only* are two different things. Your variable is *constant*, but the array it's pointing to isn't *read-only* – Matt Burland May 02 '14 at 20:44
  • 2
    So 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? – Nick Rolando May 31 '22 at 21:07
  • @KhurshidAnsari - The above is not incorrect. What code do you think works in a way that contradicts the above? Note that unless you're doing `const x = ____;` and the later doing `x = ____`, the code you're using does not contradict the above. – T.J. Crowder Feb 17 '23 at 10:49
86

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"]
Guilherme Sehn
  • 6,727
  • 18
  • 35
  • 2
    By 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 do `five++` I'm not changing the constant, just the number it points to. – Anthony Jul 19 '18 at 02:34
  • 4
    @Anthony the reference thing only works for arrays and objects, not primitive values – Guilherme Sehn Jul 19 '18 at 13:37
  • 6
    @Anthony In your example, you're changing the number that the variable `five` points to (the variable `five` 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; if `x` 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. – ShreevatsaR May 18 '19 at 00:14
20

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.
Atul O Holic
  • 6,692
  • 4
  • 39
  • 74
16

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.

thorsday
  • 346
  • 1
  • 5
  • Swift is an example of a language which does not work like this. `let someArray = ["one"]; someArray.append("two")` fails to compile with `error: cannot use mutating member on immutable value: 'someArray' is a 'let' constant` and `note: change 'let' to 'var' to make it mutable`. – user137369 Mar 28 '22 at 20:45
  • Explaining 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 Apr 18 '22 at 00:37
9

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
ubair noor
  • 91
  • 1
  • 1
8

I think this would give you more clarity on the issue : https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .

Basically it boils down to the const always pointing to the same address in memory. You can change the value stored in that address but cannot change the address the const is pointing too.

The definition of const you mentioned will hold true when the const is pointing to an address that holds a primitive value . This is because you cannot assign a value to this const without changing its address (because this is how assigning primitive values work) and changing the address of a const is not allowed.

Where as if the const is pointing to non-primitive value , it is possible to edit the value of the address.

Zyxmn
  • 99
  • 2
  • 6
  • here 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): https://www.youtube.com/watch?v=9ooYYRLdg_g – user1063287 Nov 08 '21 at 13:28
4

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.

In addition, an also important note:

Global constants do not become properties of the window object ...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Benjamin West
  • 839
  • 6
  • 6
1

The value of a const can't be changed through reassignment, and it can't be redeclared.

const testData = { name:"Sandeep",lastName:"Mukherjee",company:"XYZ"}

First case

testData = {name:"hello"}
console.log(testData);//throws an Error:Assignment to constant variable
Here we are reassigning testData again

Second case

const testData = {name:"Sandeep",lastName:"Mukherjee",company:"ABC"}
console.log(testData); //throws an Error: Identifier 'testData' has already been declared
Here we are redeclaring testData again

When a variable is declared using const it means it points to some memory location the behaviour of const is we can manipulate the value stored in that memory location but not the memory location,when we reassign/redeclare the const variable it does not allow to change the memory location

We can change the value of a specific key

testData.company = "Google"
 console.log(testData);
 //{ name: 'Sandeep', lastName: 'Mukherjee', company: 'Google' }

We can add any new key value pair to it

 testData.homeTown = "NewYork"
 console.log(testData)
 //{name: 'Sandeep',lastName:'Mukherjee',company:'Google',homeTown: 'NewYork'}
Sandeep Mukherjee
  • 673
  • 1
  • 9
  • 17
0

Because in const you can change the values of an object, so the object does not actually store the assignment data but instead, it points to it. so there is a difference between primitives and objects in Javascript.

0

const variable stores the address (memory address such as 0xFF2DFC) that is constant.

The constant is NOT the content at the memory.

constant is memory address ONLY

Thank you for reading.

Thanh Do
  • 19
  • 4
0

const MY_OBJECT = {'key': 'value'};

// Attempting to overwrite the object throws an error // Uncaught TypeError: Assignment to constant variable. MY_OBJECT = {'OTHER_KEY': 'value'};

// However, object keys are not protected, // so the following statement is executed without problem MY_OBJECT.key = 'otherValue'; // Use Object.freeze() to make object immutable

// The same applies to arrays const MY_ARRAY = []; // It's possible to push items into the array MY_ARRAY.push('A'); // ["A"] // However, assigning a new array to the variable throws an error // Uncaught TypeError: Assignment to constant variable. MY_ARRAY = ['B'];

0

In your constant is saved not the object, but link to the object.

You can't change this link, because it is constant. But object you can change.

Victoria
  • 1
  • 1
0

First of all const declared variables cannot be redeclared or reassigned.

const foo = 5; //initializing to a primitive data type , Assigned to the value

const bar = [1,2,3]; //initializing to an object(array,object,function,...) , Assigned to the reference of the object

If you are trying to reassign a variable with const you will get Uncaught TypeError:Assignment to constant variable.

You can't do either of this!

const five=5; // initialized to a value
five=6;       // trying to reassign

const obj={};
obj = {foo:"foo",bar:"bar"}; //trying to reassign 

But you can modify object like this

const obj ={};
obj.foo="foo";
obj.bar="bar";
console.log(obj); //{foo:"bar,bar:"bar"}

const arr=[];
arr[0] = 1;
arr[1] = 2;
arr[3] = 4;
console.log(arr); //[1,2,undefined,4]

Note: We're not changing the reference, just changing the data that the reference points to.

Feel free to comment if any doubts...

Praveen
  • 3
  • 3