Ключевое слово 'const' не делает значение неизменным. Что это значит?

85

Там это определение Const в Исследуя ES6 доктором Акселем Rauschmayer:

constработает как let, но объявляемая вами переменная должна быть немедленно инициализирована со значением, которое нельзя изменить впоследствии . […]

const bar = 123;
bar = 456;  // TypeError: `bar` is read-only

а потом он пишет

Ловушка: const не делает значение неизменным

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

Я немного запутался в этой ловушке. Может ли кто-нибудь четко определить constпричину этой ловушки?

Мукунд Кумар
источник
38
MDN объяснение ясно: «Декларация Const создает только для чтения ссылку на значение Это не означает , что значение, которое имеет неизменен, так что идентификатор переменной не может быть переназначен , например, в случае , если содержание является.. Объект , это означает, что сам объект все еще может быть изменен ". (курсив мой)
Херардо Фуртадо
4
Это означает, что если значение является изменяемым (например, если это объект), вы все равно можете изменять этот объект (например, обновлять, добавлять, удалять свойства).
Феликс Клинг,
2
const x = "immutable"неизменен, потому что Stringнеизменен. constзапрещает просто переназначение.
3
@ibrahimmahrir: передача в ссылке (что делает JavaScript для объектов) не является таким же , как проход по ссылке (которая описывает взаимосвязь между креплениями, значение не имеет значения).
Феликс Клинг,
2
@ibrahimmahrir: Да, вот в чем проблема. Термин « передача по ссылке» имеет очень специфическое значение .
Феликс Клинг,

Ответы:

97

MDN красиво резюмирует:

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

Более кратко: const создает неизменяемую привязку.

Другими словами: const, как и var, дает вам изменяемый фрагмент памяти, в котором вы что-то храните. Однако константа требует, чтобы вы продолжали ссылаться на тот же кусок памяти - вы не можете переназначить переменную другому фрагменту памяти, потому что ссылка на переменную постоянна.

Чтобы действительно сделать что-то постоянным и неизменным после того, как вы это объявили, вам нужно использовать что-то вроде Object.freeze(). Однако это мелочь и работает только с парами ключ / значение. Для замораживания всего объекта требуется немного больше усилий. Еще сложнее делать это многократно и эффективно. Если вам это действительно нужно, я бы рекомендовал попробовать что-нибудь вроде Immutable.js.

Майк Пост
источник
20
В терминах C: если нормальное var x- это а struct Object *x, то const xэто а struct Object *const x. Указатель нельзя изменить; то, на что он указывает, может.
Фонд
151

Когда вы делаете что-то constна JavaScript, вы не можете переназначить саму переменную для ссылки на что-то еще. Однако переменная по-прежнему может ссылаться на изменяемый объект.

const x = {a: 123};

// This is not allowed.  This would reassign `x` itself to refer to a
// different object.
x = {b: 456};

// This, however, is allowed.  This would mutate the object `x` refers to,
// but `x` itself hasn't been reassigned to refer to something else.
x.a = 456;

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

Конфеты мармелад
источник
18
Этот ответ намного лучше принятого. Более лаконичный и содержит реальный пример кода. (Другими словами,
переходим
16

Переплет

constи letобъявления контролируют, разрешены ли повторные привязки (также известные как переназначения) между идентификаторами и значениями:

const x = "initial value";
let y = "initial value";

// rebinding/reassignment

try { x = "reassignment" } catch(e) { console.log(x) } // fails

y = "reassignment"; // succeeds
console.log(y);

Неизменность

Неизменяемость контролируется на уровне типа. Objectявляется изменяемым типом, тогда Stringкак это неизменяемый тип:

const o = {mutable: true};
const x = "immutable";

// mutations

o.foo = true; // succeeds
x[0] = "I"; // fails

console.log(o); // {mutable: true, foo: true}
console.log(x); // immutable


источник
1

const означает: вы не можете изменить изначально присвоенное значение.

Сначала определите, что такое значение в js. Значением могут быть: логические значения, строки, числа, объекты, функции и неопределенные значения.

Типа: Люди зовут тебя по имени, оно не меняется. Однако вы меняете одежду. Связывания между людьми , и вы это ваше имя. Остальное можно изменить. Простите за странный пример.

Итак, позвольте мне привести несколько примеров:

// boolean
const isItOn = true;
isItOn = false;           // error

// number
const counter = 0;
counter++;                // error

// string
const name = 'edison';
name = 'tesla';           // error

// objects
const fullname = {
  name: 'albert',
  lastname: 'einstein'
};

fullname = {              // error
  name: 'werner',
  lastname: 'heisenberg'
};
// NOW LOOK AT THIS:
//
// works because, you didn't change the "value" of fullname
// you changed the value inside of it!
fullname.name = 'hermann';

const increase = aNumber => ++aNumber;
increase = aNumber => aNumber + 1;      // error

// NOW LOOK AT THIS:
//
// no error because now you're not changing the value
// which is the decrease function itself. function is a
// value too.
let anotherNumber = 3;
const decrease = () => --anotherNumber;

anotherNumber = 10;             // no error
decrease();                     // outputs 9

const chaos = undefined;
chaos = 'let there be light'    // error

const weird = NaN;
weird = 0                       // error

Как видите, если вы не измените «первое» присвоенное значение на константу, ошибки не будет. Всякий раз, когда вы пытаетесь изменить первое присвоенное значение на что-то другое, он сердится и выдает ошибку.

Итак, это второе, что вы можете знать при использовании const. То есть он должен быть инициализирован значением в своем объявлении, иначе он разозлится.

const orphan;                    // error
const rich = 0;                  // no error
Inanc Gumus
источник
0

ES6/ ES2015 constключевое слово:

constИспользуется ключевое слово , чтобы объявить переменную Scoped блок (например , объявить с let). Разница между объявлением переменной с помощью constи letзаключается в следующем:

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

Пример:

// we declare variable myVariable
let myVariable;

// first assignment
myVariable = 'First assingment';
// additional assignment
myVariable = 'Second assignment';

// we have to declare AND initialize the variable at the same time
const myConstant = 3.14;

// This will throw an error
myConstant = 12;

В приведенном выше примере мы можем наблюдать следующее:

  1. Переменная, myVariableобъявленная с помощью, letможет быть сначала объявлена, а затем назначена.
  2. Переменная, myConstantобъявленная с помощью const, должна быть объявлена ​​и назначена одновременно.
  3. Когда мы пытаемся переназначить переменную, myConstantмы получаем следующую ошибку:

Uncaught TypeError: присвоение постоянной переменной

Предостережение: переменная, присвоенная с помощью const, все еще изменяема:

Переменная, объявленная с помощью, constпросто не может быть переназначена, она все еще изменяема . Изменяемость означает, что структура данных (объект, массив, карта и т. Д.), Которая была присвоена constпеременной, все еще может быть изменена (т.е. видоизменена). Примеры мутации:

  1. Добавление / удаление / изменение свойства объекта
  2. Изменение значения массива по определенному индексу массива

Если вы действительно хотите, чтобы объект не изменялся, вам нужно будет использовать что-то вроде Object.freeze(). Это метод, который замораживает объект. Замороженный объект больше нельзя изменить, и нельзя добавить новые свойства.

Пример:

const obj = {prop1: 1};

obj.prop1 = 2;
obj.prop2 = 2;

console.log(obj);

// We freeze the object here
Object.freeze(obj);

obj.prop1 = 5;
delete obj.prop2;

// The object was frozen and thus not mutated
console.log(obj);

Виллем ван дер Вин
источник