- PVSM.RU - https://www.pvsm.ru -

ES6 const это не про иммутабельность

Определение 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, и гарантирует, что нового присвоения не будет. Использование оператора присвоения, а также унарных [1] или постфиксных [2] операторов — и ++ вызовет ошибку 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() [3]. Этот метод нам доступен со времён ES5.

const foo = Object.freeze({
	'bar': 27
});
foo.bar = 42; // TypeError exception при условии использования strict mode;
console.log(foo.bar);
// → 27

Но помните, что Object.freeze() поверхностный, т.е. у замороженного объекта до сих пор останется возможность изменять вложенные объекты. На MDN [3] есть пример глубокой заморозки, метод deepFreeze, который позволит сделать полностью иммутабельный объект.

Object.freeze() работает только с объектами ключ-значение, и в настоящее время нет возможности сделать иммутабельными такие объекты, как Date, Map или Set.

Тут [4] есть предложение по неизменяемым данным для будущего стандарта ECMAScript.

const vs. let

Единственное различие между const и let в том, что const обещает — переприсвоения не произойдёт.

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

  • Если это возможно — всегда используйте const по умолчанию
  • let используйте тогда, когда необходимо переприсвоение
  • var не должен использоваться вообще

Автор: Delias

Источник [5]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/197719

Ссылки в тексте:

[1] унарных: https://tc39.github.io/ecma262/#sec-unary-operators

[2] постфиксных: https://tc39.github.io/ecma262/#sec-postfix-increment-operator

[3] Object.freeze(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

[4] Тут: https://github.com/sebmarkbage/ecmascript-immutable-data-structures

[5] Источник: https://habrahabr.ru/post/312088/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best