Pull to refresh

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

Reading time2 min
Views12K
Original author: Mathias Bynens
Определение 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 не должен использоваться вообще
Tags:
Hubs:
+14
Comments67

Articles

Change theme settings