Символы впервые появились в JavaScript в ES6. Давайте посмотрим, что они из себя представляют, как их создавать и как вы можете их использовать (или увидеть, как их использовать).

Символы - это новый примитивный тип данных

Вы правильно прочитали - ES6 представил в JavaScript целый новый примитивный тип данных. Что отличает символы от примитивных типов данных до ES6 (string, number, boolean, null, undefined), так это их уникальность - каждое значение символа гарантированно уникально.

Давайте посмотрим, как создать значение типа symbol:

const dug = Symbol();
dug; // Symbol()

Все просто, правда? Мы объявили константу и присвоили ей возвращаемое значение функции. JavaScript предоставляет встроенную функцию Symbol(), которая просто возвращает новое значение типа symbol.

Если мы хотим, мы можем передать необязательное описание для нашего символа. Описание не имеет ничего общего со значением самого символа. Добавление описания выглядит так:

const describeMe = Symbol('description');
describeMe; // Symbol(description)

Еще раз обратите внимание, что в значении символа, хранящемся в describeMe, нет ничего особенного - наше описание отображается только для целей отладки и не влияет на само значение символа.

Символы уникальны

Здесь следует отметить одну важную вещь: значения символов, которые мы только что сохранили, полностью уникальны. Попробуйте ввести эти операторы в свою консоль, чтобы убедиться в этом:

const dug = Symbol();
dug === Symbol(); // false
Symbol() === Symbol(); // false
dug === dug; // true

Итак - как мы можем использовать эти уникальные значения? Одно из основных применений символов может заключаться в представлении абстрактных понятий, таких как цвета. До ES6 мы могли сохранить концепцию цвета красный в виде строки, например:

const colourRed = 'red';

Однако довольно легко создать строковые значения, точно эквивалентные colourRed, которые на самом деле не то же самое, что красный цвет:

const colourRed = 'red';
const siteName = 'reddit';
const shortSiteName = siteName.slice(0,3);
shortSiteName; // "red"
colourRed === shortSiteName; // true

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

const colourRed = Symbol();
const siteName = 'reddit';
const shortSiteName = siteName.slice(0,3);
shortSiteName; // "red"
colourRed === shortSiteName; // false

(См. Отличный пример Изучение ES6 доктора Акселя Раушмайера.)

Символы могут использоваться как ключи на объекте

Чаще всего символы используются в качестве ключей объекта. Поскольку символы уникальны, мы можем добавить к объекту столько свойств, сколько захотим, не беспокоясь о конфликте ключей. Более того, поскольку значения символов не наблюдаются напрямую (все они просто возвращают Symbol() в консоли), они обладают анонимизирующим эффектом при использовании в качестве ключей.

Для иллюстрации давайте создадим объект с несколькими свойствами:

const abby = {};
abby['legs'] = 4;
abby['ears'] = 2;
abby['nose'] = 1;

Затем мы создадим некоторые значения символов:

const hasFleas = Symbol();
const smellsBad = Symbol();

Наконец, давайте воспользуемся этими значениями символов для хранения дополнительных данных о нашем объекте:

abby[hasFleas] = false;
abby[smellsBad] = true;

Давайте посмотрим, как наш объект оценивается в консоли:

abby;
// Returns the following -
// 
// ears: 1
// legs: 4
// nose: 1
// Symbol(): false
// Symbol(): true

Обратите внимание, что наша информация о блохах и запахе Эбби (собаки) читаема, но ключи, идентифицирующие эту информацию, анонимны. С первого взгляда мы действительно не можем сказать, какое свойство принадлежит к какому.

Однако в лучшем случае это обеспечивает небольшую неясность - это не практики, достаточной для защиты личных данных.

Символы могут хранить метаданные об объектах

Еще одна интересная вещь происходит, когда мы используем символы в качестве ключей к объекту - свойства с символьными ключами пропускаются при итерации. Например, если мы перебираем наш объект abby, происходит следующее:

for (prop in abby) {
  console.log(prop, abby[prop]);
}
// Output
//
// legs 4
// ears 2
// nose 1

Как видите, символы дают нам возможность хранить дополнительную информацию - метаданные - об объектах, сохраняя при этом нашу способность взаимодействовать с ними привычными способами. Довольно круто!

Вот оно что

Теперь мы на одной волне! Помните эти ключевые выводы:

  • Символы - это новый примитивный тип данных
  • Значения символов уникальны (в большинстве случаев - но это уже история другого дня: см. методы глобального реестра символов)
  • Значения символов могут использоваться в качестве ключей объекта (вместо строковых значений) и никогда не будут конфликтовать с уже существующими ключами.
  • Поскольку символьные ключи пропускаются при итерации по объекту, символы позволяют нам хранить дополнительные метаданные об объектах.

Вы используете символы в своем коде? Дайте мне знать в комментариях или найдите меня в Twitter!