Подтвердить что ты не робот

Почему я могу изменить значение константы в javascript

Я знаю, что ES6 еще не стандартизирован, но количество браузеров в настоящее время поддерживает const ключевое слово в JS.

В спецификации указано, что:

Значение константы не может изменяться при повторном присвоении, а константа не может быть повторно объявлена. Из-за этого, хотя это можно объявить константу без ее инициализации, это было бы бесполезно это сделать.

и когда я делаю что-то вроде этого:

const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];

Я вижу, что все в порядке xxx все еще 6 и yyy есть [].

Но если я делаю yyy.push(6); yyy.push(1);, мой постоянный массив был изменен. Сейчас это [6, 1] и, кстати, я все еще не могу изменить его с помощью yyy = 1;.

Я это ошибка, или я чего-то не хватает? Я попробовал его в последнем хроме и FF29

4b9b3361

Ответ 1

В документации говорится:

... константа не может измениться путем переназначения
... константа не может быть повторно объявлена

Когда вы добавляете в массив или объект, вы не переназначаете или не объявляете константу, она уже объявлена и назначена, вы просто добавляете в "список", на который указывает константа.

Так что это работает нормально:

const x = {};

x.foo = 'bar';

console.log(x); // {foo : 'bar'}

x.foo = 'bar2';

console.log(x); // {foo : 'bar2'}  

и это:

const y = [];

y.push('foo');

console.log(y); // ['foo']

y.unshift("foo2");

console.log(y); // ['foo2', 'foo']

y.pop();

console.log(y); // ['foo2']

но ни один из них:

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

Ответ 2

Это происходит потому, что ваша константа на самом деле хранит ссылку на массив. Когда вы присоединяете что-то к вашему массиву, вы изменяете не постоянное значение, а массив, на который оно указывает. То же самое произошло бы, если бы вы присвоили объект константе и попытались изменить любое его свойство.

Если вы хотите заморозить массив или объект, чтобы его нельзя было изменить, вы можете использовать метод Object.freeze, который уже является частью ECMAScript 5.

const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]

Ответ 3

Это последовательное поведение с каждым языком программирования, о котором я могу думать.

Рассмотрим C - массивы - это просто прославленные указатели. Постоянный массив означает, что значение указателя не изменится, но на самом деле данные, содержащиеся в этом адресе, свободны.

В javascript вам разрешено вызывать методы с постоянными объектами (конечно же, в противном случае постоянные объекты не будут служить большой цели!) Эти методы могут иметь побочный эффект изменения объекта. Поскольку массивы в javascript являются объектами, это относится и к ним.

Все, что вы уверены в том, что константа всегда будет указывать на один и тот же объект. Свойства самого объекта могут быть изменены.

Ответ 4

Объявление const создает ссылку на чтение только для чтения. Это не означает, что значение, которое оно имеет, является неизменным, просто чтобы идентификатор переменной не мог быть переназначен. Например, в случае, когда контент является объектом, это означает, что содержимое объекта (например, его параметры) может быть изменено.

Кроме того, важно также отметить:

Глобальные константы не становятся свойствами оконного объекта...

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

Ответ 5

Я думаю, что это даст вам больше ясности в этом вопросе: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0.

В основном это сводится к const всегда указывающей на тот же адрес в памяти. Вы можете изменить значение, сохраненное в этот адрес, но не может изменить этот адрес const указывает тоже.

Определение const вы упомянули, будет иметь значение, если const указывает на адрес, который содержит примитивное значение. Это связано с тем, что вы не можете присвоить значение этой const без изменения ее адреса (потому что это так, как задание примитивных значений работает) и изменение адреса const запрещено.

Где, как если бы const указывала на не-примитивное значение, можно изменить значение адреса.

Ответ 6

Прочитал эту статью, когда искал, почему я смог обновить объект даже после определения его как const. Таким образом, суть в том, что это не объект напрямую, а содержащиеся в нем атрибуты, которые можно обновлять.

Например, мой объект выглядит так:

const number = {
    id:5,
    name:'Bob'
};

Приведенные выше ответы правильно указывают на то, что это объект, который является const, а не его атрибут. Следовательно, я смогу обновить идентификатор или имя, выполнив:

number.name = 'John';

Но я не смогу обновить сам объект как:

number = {
    id:5,
    name:'John'
  };

TypeError: Assignment to constant variable.