Почему я могу изменить значение константы в 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
Ответы
Ответ 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.