Symbol

Символ (Symbol) — примитивный тип, значения которого создаются с помощью вызова функции Symbol. Каждый созданный символ уникален.

Символы могут использоваться в качестве имён свойств в объектах. Символьные свойства могут быть прочитаны только при прямом обращении и не видны при обычных операциях.

Синтаксис

Symbol([описание])

Параметры

описание
Необязательный, строка. Описание символа, которое может быть использовано во время отладки, но не для доступа к самому символу.

Описание, Комментарии

Symbol.for()

Метод Symbol.for(key) ищет ранее созданный разделяемый символ по заданному ключу и возвращает его, если он найден. В противном случае создаётся новый разделяемый символ для данного ключа в глобальном реестре символов.

Синтаксис

Symbol.for(key);

Параметры

key
Строка, обязательный. Идентификатор символа (также используется в качестве описания символа).

Описание

В противоположность вызову Symbol(), функция Symbol.for() создаёт символ, доступный в глобальном списке реестра символов. Symbol.for() не создаёт новый символ при каждом вызове, вместо этого, метод сначала проверяет, существует ли символ с заданным идентификатором в реестре — и возвращает его, если тот присутствует. Если символ с заданным ключом не найден, Symbol.for() создаст новый глобальный символ.

Глобальный реестр

Глобальный реестр символов — это список со следующей структурой записей и пустой при инициализации:

Элемент глобального реестра символов
ПолеЗначение
[[key]] Строка, используемая в качестве идентификатора.
[[symbol]] Символ, хранящийся глобально.

Пример

Symbol.for("foo");   // создаёт новый глобальный символ
Symbol.for("foo");   // возвращает символ, созданный прежде

// Одинаковый глобальный символ, но не локальный
let s = Symbol.for("bar") === Symbol.for("bar");   // true
s += '\n' + ( Symbol("bar") === Symbol("bar") );   // false

// Идентификатор также используется в качестве описания
var sym = Symbol.for("mario");
s += '\n' + ( sym.toString() );      // "Symbol(mario)"
alert(s);

Symbol.keyFor()

Метод Symbol.keyFor(sym) получает ключ для заданного символа из глобального реестра символов.

Синтаксис

Symbol.keyFor(sym);

Параметры

sim
Символ, обязательный. Символ, ключ которого требуется найти.

Возвращаемое значение

Строка с ключом заданного символа, если он есть в глобальном реестре символов, либо undefined, если его там нет.

Пример

var globalSym = Symbol.for("foo"); // Создаёт новый глобальный символ
let s = Symbol.keyFor(globalSym); // "foo"

var localSym = Symbol();
s += '\n' + Symbol.keyFor(localSym); // undefined

// Известные символы не является символами,
// которые находятся в глобальном реестре символов
s += '\n' + Symbol.keyFor(Symbol.iterator) // undefined
alert(s);

Системные символы

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

Эти символы перечислены в спецификации в таблице Well-known symbols:

Итого

Символ (symbol) – примитивный тип данных, использующийся для создания уникальных идентификаторов.

Символы создаются вызовом функции Symbol(), в которую можно передать описание (имя) символа.

Даже если символы имеют одно и то же имя, это – разные символы. Если мы хотим, чтобы одноимённые символы были равны, то следует использовать глобальный реестр: вызов Symbol.for(key) возвращает (или создаёт) глобальный символ с key в качестве имени. Многократные вызовы команды Symbol.for с одним и тем же аргументом возвращают один и тот же символ.

Символы имеют два основных варианта использования:

  1. «Скрытые» свойства объектов. Если мы хотим добавить свойство в объект, который «принадлежит» другому скрипту или библиотеке, мы можем создать символ и использовать его в качестве ключа. Символьное свойство не появится в for..in, так что оно не будет нечаянно обработано вместе с другими. Также оно не будет модифицировано прямым обращением, так как другой скрипт не знает о нашем символе. Таким образом, свойство будет защищено от случайной перезаписи или использования.

    Так что, используя символьные свойства, мы можем спрятать что-то нужное нам, но что другие видеть не должны.

  2. Существует множество системных символов, используемых внутри JavaScript, доступных как Symbol.*. Мы можем использовать их, чтобы изменять встроенное поведение ряда объектов.

Технически символы скрыты не на 100%. Существует встроенный метод Object.getOwnPropertySymbols(obj) – с его помощью можно получить все свойства объекта с ключами-символами. Также существует метод Reflect.ownKeys(obj), который возвращает все ключи объекта, включая символьные. Так что они не совсем спрятаны. Но большинство библиотек, встроенных методов и синтаксических конструкций не используют эти методы.