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?
Qual das opções a seguir descreve símbolos "conhecidos"?