Символы — это примитивный тип, представленный в ES6 и используемый в качестве нестроковых имен свойств. Чтобы понимать символы, важно знать, что в JavaScript базовый тип Object представляет собой неупорядоченную коллекцию свойств, каждое из которых имеет имя и значение. Имена свойств обычно (до ES6) были строками. Однако в ES6 и более поздних версиях символы также можно использовать в качестве имен свойств:

// String that can be used as a property name
let strname = "string name";
// Symbol that can be used as a property name
let symname = Symbol("propname");
//=> "string": strname is a string
typeof strname
//=> "symbol": symname is a symbol
typeof symname
​
// Create a new object
let o = {};
// Define a property with a string name
o[strname] = 1;
// Define a property with a symbol name
o[symname] = 2;
//=> 1: Access property with string name
o[strname]
// => 2: Access property with symbol name
o[symname]

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

(Мягкие навыки для программистов: amazon.com/dp/B0CF599P8J)

На практике символы часто используются как механизм расширений языка. В ES6 появился цикл for/of и концепция итерируемых объектов, что требовало определения стандартизированного способа, с помощью которого классы могут сделать себя итерируемыми. Однако использование какой-либо конкретной строки в качестве имени этого метода итератора потенциально может привести к конфликту с существующим кодом. Здесь в игру вступают символы. Symbol.iterator — это значение символа, которое можно использовать в качестве имени метода, чтобы сделать объект итерируемым.

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

let s = Symbol("syn_x");
// => "Symbol(syn_x)"
s.toString()

Единственный интересный метод для значений символов — toString(). Однако есть еще две функции, связанные с символами, о которых стоит знать. Иногда при использовании символов вы хотите, чтобы они были закрытыми для вашего кода, чтобы гарантировать, что ваши свойства не будут конфликтовать со свойствами из другого кода. Но в других случаях вам может потребоваться определить символы, которые можно использовать совместно с другим кодом. Например, если вы определяете расширение и хотите, чтобы его использовал другой код, аналогично механизму Symbol.iterator, упомянутому ранее.

Чтобы определить символы, которые могут использоваться совместно с другим кодом, в JavaScript имеется глобальный реестр символов. Функция Symbol.for() принимает строковый параметр и возвращает значение символа, связанное с этой строкой. Если со строкой не связан ни один символ, будет создан и возвращен новый символ; в противном случае он вернет существующий символ. Другими словами, Symbol.for() и Symbol() совершенно разные: Symbol() никогда не возвращает одно и то же значение, а Symbol.for() всегда возвращает одно и то же значение при вызове с одной и той же строкой. Строка, предоставленная Symbol.for(), появится в выходных данных toString() (при возврате значения символа). Кроме того, эту строку можно получить с помощью Symbol.keyFor(), передав возвращаемый символ:

let s = Symbol.for("shared");
let t = Symbol.for("shared");
// => true
s === t
// => "Symbol(shared)"
s.toString()
// "shared"
Symbol.keyFor(t)

(Мягкие навыки для программистов: amazon.com/dp/B0CF599P8J)