Определение 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 не должен использоваться вообще
Автор: Delias