Зачем нужен Symbol?


В JS есть тип данных — Symbol. Название не говорящее само за себя сходу, и непонятно зачем он нужен. Давайте разбираться.

Вообще Symbol — это встроенный в язык инструмент для создания гарантированно уникальных и неизменных значений, идентификаторов.

const mySymbol = Symbol();

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

Symbol появился в стандарте ES2015, когда язык сильно менялся и в нём появлялись новые методы. При появлении новых фич нужно было не «сломать» старые.

В частности нужна была возможность добавлять в объекты новые свойства, но чтобы:

  1. Все методы для «перебора», например, for-in или Object.keys(), продолжили работать как раньше;
  2. Не было риска «пересечения» названий новых и уже существующих свойств.

Про перебор

Например, у объекта есть условно три свойства:

const myObject = { first: "1", second: "2", third: "3" };

Предположим, что некая программа рассчитывает, что у объекта есть ровно три свойства, к примеру, при переборе в цикле for-in. И если комитет разработки языка вдруг решит, что у всех объектов в JS должно просто появиться новое четвёртое свойство, например, coolNewProperty, то программа сломается.

А вот если создать новое свойство объекта как символ, то оно не появится в списке всех свойств при итерации.

const myObject = { first: "1", second: "2", third: "3" };
const coolNewProperty = Symbol();
myObject[coolNewProperty] = "coolNewValue";
for (let property in myObject) {
console.log(property);
// Выведется first second third
}
console.log(myObject[coolNewProperty]);
// Выведется coolNewValue

Про «пересечение» имён

С помощью символа можно «безопасно» создать новое свойство в объекте, не боясь, что в будущих версиях языка или сторонних библиотеках появится свойство с таким же названием.

let myArray = [1, 2, 3];
const reverse = Symbol();
Array.prototype[reverse] = () => console.log("custom reverse");
console.log(myArray.reverse());
// Выведется [3, 2, 1]
console.log(myArray[reverse]());
// Выведется custom reverse