Символ

Символы — это относительно новый примитив, представленный в ES6. Примитив символа представляет собой уникальное значение, которое никогда не конфликтует ни с каким другим значением, включая значения других примитивов символов. Два строковых примитива, состоящих из одинаковых символов, оцениваются как строго равные:

String() === String()
> true

String( "My string." ) === String( "My string." );
> true

Однако никакие два символа, созданные с помощью функции Symbol() не могут быть строго равными:

Symbol() === Symbol()
> false

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

const mySymbol = Symbol( "Desc" );

const myObject = {

}

myObject
> Object { Symbol("Desc"): "propSymbol" }

Существует три типа символов:

  • Символы, созданные с помощью Symbol()
  • Общие символы, которые устанавливаются и извлекаются из глобального реестра символов с помощью Symbol.for()
  • «Общеизвестные символы» определяются как статические свойства объекта «Символ». Эти символы содержат внутренние методы, которые нельзя случайно перезаписать.

Symbol() принимает описание (или «имя символа») в качестве необязательного аргумента. Эти описания представляют собой удобочитаемые метки для целей отладки и не влияют на уникальность результата. Любой вызов Symbol возвращает совершенно уникальный примитив символа, даже если несколько вызовов имеют одинаковые описания:

Symbol( "My symbol." ) === Symbol( "My symbol." );
> false

Как и другие примитивные типы данных, символы наследуют методы и свойства от своего прототипа . Например, вы можете получить доступ к описанию как унаследованному свойству созданного символа:

let mySymbol = Symbol( "My symbol." );

mySymbol.description
> "My symbol."

Но вы не можете создать символ, используя new ключевое слово:

let mySymbol = new Symbol();

> Uncaught TypeError: Symbol is not a constructor

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

Общие символы

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

let sharedSymbol = Symbol.for( "My key." );

sharedSymbol === Symbol.for( "My key." )
> true

Эти ключи не имеют функционального дублирования с описаниями, присвоенными созданным автором примитивам Symbol . Чтобы получить доступ к символу в реестре символов, вы должны сначала создать его с помощью for() :

Symbol( "String" ) === Symbol( "String" );
> false

Symbol( "String" ) === Symbol().for( "String" );
> false

Symbol().for( "String" ) === Symbol().for( "String" );
> true

Чтобы получить ключ для любого символа из реестра символов, используйте Symbol.keyFor() :

let mySymbol = Symbol.for( "Key." );

Symbol.keyFor( mySymbol ) ;
> "Key."

«Известные» символы

Хорошо известные символы — это статические свойства объекта Symbol , каждое из которых само по себе является символом. Хорошо известные символы предоставляют уникальные ключи свойств для доступа и изменения встроенных методов JavaScript, предотвращая при этом непреднамеренную перезапись основного поведения.

Symbol;
> function Symbol()
    asyncIterator: Symbol(Symbol.asyncIterator)
    for: function for()
    hasInstance: Symbol("Symbol.hasInstance")
    isConcatSpreadable: Symbol("Symbol.isConcatSpreadable")
    iterator: Symbol(Symbol.iterator)
    keyFor: function keyFor()
    length: 0
    match: Symbol("Symbol.match")
    matchAll: Symbol("Symbol.matchAll")
    name: "Symbol"
    prototype: Object {  }
    replace: Symbol("Symbol.replace")
    search: Symbol("Symbol.search")
    species: Symbol("Symbol.species")
    split: Symbol("Symbol.split")
    toPrimitive: Symbol("Symbol.toPrimitive")
    toStringTag: Symbol("Symbol.toStringTag")
    unscopables: Symbol("Symbol.unscopables")
    <prototype>: function ()

Поскольку символы являются функцией, специфичной для ES6, эти символические значения предназначены для использования в качестве «точек расширения» для разработчиков, изменяющих поведение JavaScript без возникновения проблем с обратной совместимостью.

Значения известных символов часто стилизуются с помощью префикса @@ или заключаются в % , чтобы отличать их ключи от их изменяемых прототипов. Например, @@match (или %match% ) — это ссылка на неизменяемый Symbol.match , а не на String.prototype.match .

Проверьте свое понимание

Можете ли вы использовать new для создания символа?

Да
Нет

Что из следующего описывает «хорошо известные» символы?

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