[Перевод - recovery mode ] ES6 const это не про иммутабельность
Определение const вводит в заблуждение, которое должно быть развеяно:
Единственная вещь, которая тут неизменяемая, это ссылка на объект. const присваивает значение ({ }) к переменной foo, и гарантирует, что нового присвоения не будет. Использование оператора присвоения, а также унарных или постфиксных операторов — и ++ вызовет ошибку TypeError.
ES6 const ничего не делает с неизменяемостью данных.
Примитивные типы данных, такие как numbers, strings, booleans, symbols, null, or undefined всегда иммутабельны.
Для того, чтобы сделать данные иммутабельными, используйте Object.freeze (). Этот метод нам доступен со времён ES5.
Но помните, что Object.freeze () поверхностный, т.е. у замороженного объекта до сих пор останется возможность изменять вложенные объекты. На MDN есть пример глубокой заморозки, метод deepFreeze, который позволит сделать полностью иммутабельный объект.
Единственное различие между const и let в том, что const обещает — переприсвоения не произойдёт.
const создаёт иммутабельную ссылку на объект, но это не значит, что значение нельзя будет изменить — нет, это значение может быть изменено. Следующий код не будет являться ошибкой:
const foo = {};
foo.bar = 42;
console.log(foo.bar);
// → 42
const arr = [0, 20, 30];
arr[0] = 10;
console.log(arr);
// → [10, 20, 30]
Единственная вещь, которая тут неизменяемая, это ссылка на объект. const присваивает значение ({ }) к переменной foo, и гарантирует, что нового присвоения не будет. Использование оператора присвоения, а также унарных или постфиксных операторов — и ++ вызовет ошибку TypeError.
const foo = 27;
// Все операции ниже вызовут ошибку
// Операторы присвоения:
foo = 42;
foo *= 42;
foo /= 42;
foo %= 42;
foo += 42;
foo -= 42;
foo <<= 0b101010;
foo >>= 0b101010;
foo >>>= 0b101010;
foo &= 0b101010;
foo ^= 0b101010;
foo |= 0b101010;
// Унарные `--` и `++`:
--foo;
++foo;
// Постфиксные `--` и `++`:
foo--;
foo++;
ES6 const ничего не делает с неизменяемостью данных.
Так как же тогда получить иммутабельное значение?
Примитивные типы данных, такие как numbers, strings, booleans, symbols, null, or undefined всегда иммутабельны.
var foo = 27;
foo.bar = 42;
console.log(foo.bar);
// → `undefined`
Для того, чтобы сделать данные иммутабельными, используйте Object.freeze (). Этот метод нам доступен со времён ES5.
const foo = Object.freeze({
'bar': 27
});
foo.bar = 42; // TypeError exception при условии использования strict mode;
console.log(foo.bar);
// → 27
Но помните, что Object.freeze () поверхностный, т.е. у замороженного объекта до сих пор останется возможность изменять вложенные объекты. На MDN есть пример глубокой заморозки, метод deepFreeze, который позволит сделать полностью иммутабельный объект.
Object.freeze () работает только с объектами ключ-значение, и в настоящее время нет возможности сделать иммутабельными такие объекты, как Date, Map или Set.
Тут есть предложение по неизменяемым данным для будущего стандарта ECMAScript.
const vs. let
Единственное различие между const и let в том, что const обещает — переприсвоения не произойдёт.
С учётом вышеизложенного, const делает код более читаемым. В пределах области видимости const всегда ссылается на тот же объект. Используя let такой гарантии нет. Поэтому следует придерживаться следующей практики:
- Если это возможно — всегда используйте const по умолчанию
- let используйте тогда, когда необходимо переприсвоение
- var не должен использоваться вообще