Символ

Символы — это относительно новый примитив, представленный в 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.