Símbolo

Os símbolos são relativamente novos introduzido no ES6. Um primitivo de símbolo representa um valor único que nunca colidirá com nenhum outro valor, incluindo os de outros primitivos de símbolo. Duas primitivas de string compostas por caracteres idênticos são avaliadas como estritamente igual:

String() === String()
> true

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

No entanto, dois símbolos criados usando a função Symbol() nunca podem ser estritamente iguais:

Symbol() === Symbol()
> false

Essa característica permite usar símbolos como chaves de propriedade exclusivas em um objeto, evitando colisões com chaves que qualquer outro código pode adicionar a esse objeto.

const mySymbol = Symbol( "Desc" );

const myObject = {

}

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

Existem três tipos de símbolos:

  • Símbolos criados com Symbol()
  • Símbolos compartilhados que são definidos e recuperados de um registro de símbolo global usando Symbol.for()
  • "Símbolos conhecidos" definidas como propriedades estáticas no objeto Symbol. Esses símbolos contêm métodos internos que não podem ser substituídos acidentalmente.

Symbol() aceita uma descrição (ou "nome de símbolo") como argumento opcional. Essas descrições são rótulos legíveis para fins de depuração e não afetam a exclusividade do resultado. Qualquer chamada para Symbol retorna uma primitivo de símbolo completamente único, mesmo se várias chamadas tiverem descrições:

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

Assim como em outros tipos de dados primitivos, os símbolos herdam métodos e propriedades o protótipo deles. Por exemplo, você pode acessar uma descrição como uma propriedade herdada do símbolo criado:

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

mySymbol
.description
> "My symbol."

Mas não é possível criar um símbolo usando a palavra-chave new:

let mySymbol = new Symbol();

> Uncaught TypeError: Symbol is not a constructor

Os símbolos não são enumeráveis, o que significa que as propriedades simbólicas não estão disponíveis ao usar métodos padrão para iterar sobre eles. O getOwnPropertySymbols() dá acesso às propriedades de símbolo de um objeto.

Símbolos compartilhados

O método Symbol.for() tenta procurar símbolos existentes em uma registro de símbolos global em todo o ambiente de execução com uma determinada string como chave e retorna o símbolo correspondente, caso seja encontrado. Caso não encontre, criará um símbolo com a chave especificada e a adiciona ao registro global:

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

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

Essas chaves não têm sobreposição funcional com as descrições atribuídas a primitivas Symbol criadas pelo autor. Para acessar um símbolo no registro de símbolos, primeiro, crie-a usando for():

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

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

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

Para recuperar a chave de qualquer símbolo do registro de símbolos, use Symbol.keyFor():

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

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

"Conhecidos" símbolos

Símbolos conhecidos são propriedades estáticas do objeto Symbol, cada um dos quais é um símbolo em si. Símbolos conhecidos fornecem chaves de propriedade exclusivas para acessar e modificar os métodos integrados do JavaScript, evitando de um comportamento malicioso seja substituído involuntariamente.

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 ()

Como os símbolos são um recurso específico do ES6, esses valores simbólicos são para ser usado como "pontos de extensão" para desenvolvedores que modificam comportamento sem introduzir problemas de compatibilidade com versões anteriores.

Valores de símbolos conhecidos geralmente são estilizados com um com o prefixo @@ ou unido em % para para diferenciar as chaves dos protótipos mutáveis. Por exemplo, @@match. (ou %match%) é uma referência ao Symbol.match imutável, não String.prototype.match.

Teste seu conhecimento

É possível usar new para criar um símbolo?

Sim
Não

Qual das opções a seguir descreve símbolos "conhecidos"?

Chaves de propriedade exclusivas para acessar e modificar as chaves métodos integrados
Símbolos que você usa com frequência
Propriedades estáticas do objeto "Symbol"