ATUALIZAÇÃO : Recentemente, surgiu um artigo brilhante da Mozilla . Leia se você estiver curioso.
Como você deve saber, eles estão planejando incluir um novo tipo primitivo Symbol no ECMAScript 6 (para não mencionar outras coisas malucas). Eu sempre pensei que a :symbol
noção em Ruby é desnecessária; em vez disso, poderíamos facilmente usar strings simples, como fazemos em JavaScript. E agora eles decidem complicar as coisas em JS com isso.
Eu não entendo a motivação. Alguém poderia me explicar se realmente precisamos de símbolos em JavaScript?
private
epublic
atributos de classe que decidiram abandonar para uma implementação de classe mais simples. Em vez dethis.x = x
você deveria fazerpublic x = x
e para variáveis privadasprivate y = y
. Eles decidiram abandonar isso para uma implementação de classe muito mais mínima. O Symbol seria uma solução alternativa necessária para obter propriedades particulares na implementação mínima.Respostas:
A motivação original para introduzir símbolos no Javascript era ativar propriedades privadas .
Infelizmente, eles acabaram sendo severamente rebaixados. Eles não são mais particulares, pois você pode encontrá-los por meio de reflexão, por exemplo, usando
Object.getOwnPropertySymbols
ou proxies.Agora eles são conhecidos como símbolos exclusivos e seu único objetivo é evitar conflitos de nomes entre propriedades. Por exemplo, o próprio ECMAScript agora pode introduzir ganchos de extensão por meio de certos métodos que você pode colocar em objetos (por exemplo, para definir seu protocolo de iteração) sem correr o risco de colidir com nomes de usuário.
Se isso é forte o suficiente, uma motivação para adicionar símbolos ao idioma é discutível.
fonte
Object.getOwnPropertySymbols
não é o único vazamento; o mais difícil é a capacidade de usar proxies para interceptar o acesso a uma propriedade "privada".Os símbolos não garantem privacidade verdadeira, mas podem ser usados para separar propriedades públicas e internas de objetos. Vamos dar um exemplo em que podemos usar
Symbol
para ter propriedades privadas.Vamos dar um exemplo em que a propriedade de um objeto não é privada.
Acima, a
Pet
propriedade da classetype
não é privada. Para torná-lo privado, precisamos criar um fechamento. O exemplo abaixo ilustra como podemos tornartype
privados usando um fechamento.Desvantagem da abordagem acima: Estamos introduzindo um fechamento extra para cada
Pet
instância criada, o que pode prejudicar o desempenho.Agora nós apresentamos
Symbol
. Isso pode nos ajudar a tornar uma propriedade privada sem o uso de fechamentos desnecessários extras. Exemplo de código abaixo:fonte
_
não garante privacidade verdadeira, mas pode ser usado para separar propriedades públicas e internas de objetos. Em outras palavras, resposta inútil.Symbols
são um novo tipo especial de objeto que pode ser usado como um nome de propriedade exclusivo nos objetos. Usar emSymbol
vez destring
's permite que diferentes módulos criem propriedades que não entrem em conflito.Symbols
também podem ser tornados privados, para que suas propriedades não possam ser acessadas por qualquer pessoa que ainda não tenha acesso direto aoSymbol
.Symbols
são um novo primitivo . Assim como asnumber
,string
eboolean
primitivos,Symbol
têm uma função que pode ser usado para criá-los. Diferente das outras primitivas,Symbols
não possui uma sintaxe literal (por exemplo, comostring
possui''
) - a única maneira de criá-las é com oSymbol
construtor da seguinte maneira:Na realidade,
Symbol
são apenas uma maneira ligeiramente diferente de anexar propriedades a um objeto - você pode facilmente fornecer osSymbols
métodos padrão conhecidos , exatamente como osObject.prototype.hasOwnProperty
que aparecem em tudo o que herdaObject
.Aqui estão alguns dos benefícios do
Symbol
tipo primitivo.Symbols
possui depuração incorporadaSymbols
pode receber uma descrição, que é realmente usada apenas para depuração para facilitar a vida ao fazer o logon em um console.Symbols
pode ser usado comoObject
chavesÉ aqui que
Symbol
as coisas ficam realmente interessantes. Eles estão fortemente entrelaçados com objetos.Symbol
podem ser atribuídos como chaves a objetos, o que significa que você pode atribuir um número ilimitado de itens exclusivosSymbol
a um objeto e garantir que eles nunca entrem em conflito com asstring
chaves ou outros itens exclusivos.Symbols
.Symbols
pode ser usado como um valor único.Vamos supor que você tem uma biblioteca de registro, que inclui vários níveis de log, como
logger.levels.DEBUG
,logger.levels.INFO
,logger.levels.WARN
e assim por diante. No código ES5, você gostaria de criar essesstring
s (sologger.levels.DEBUG === 'debug'
) ounumber
s (logger.levels.DEBUG === 10
). Ambos não são ideais, pois esses valores não são únicos, masSymbol
s são! Entãologger.levels
simplesmente se torna:Leia mais neste ótimo artigo .
fonte
log.levels = {DEBUG: Symbol('debug')
e não simplesmentelog.levels = {DEBUG:'debug'}
. no final, é o mesmo. Eu acho que vale a pena mencionar que os símbolos são invisíveis quando iteram sobre as chaves de um objeto. essa é a "coisa" deles{}
e obter o mesmo resultado (como valor exclusivo), ou talvez um literal seja o preferido nesse projeto, ou você pode dizer que é necessário ler o documento primeiro. pessoalmente acho que fornecem uma boa legibilidade do sentido único no códigoSymbol("some message")
seja{message:'some message'}
, torna-se , sem dúvida o objeto se sai melhor aqui, pois você pode adicionar vários campos.Este post é sobre o
Symbol()
, fornecido com exemplos reais que eu poderia encontrar / criar e fatos e definições que eu poderia encontrar.TLDR;
O
Symbol()
é o tipo de dados, introduzido com o lançamento do ECMAScript 6 (ES6).Existem dois fatos curiosos sobre o símbolo.
o primeiro tipo de dados e apenas o tipo de dados em JavaScript que não possui literal
qualquer variável, definida com
Symbol()
, obtém conteúdo exclusivo, mas não é realmente privado .qualquer dado possui seu próprio símbolo e, para os mesmos dados, os símbolos seriam os mesmos . Mais informações no parágrafo a seguir, caso contrário, não é um TLRD; :)
Como inicializo o símbolo?
1. Para obter um identificador exclusivo com um valor depurável
Você pode fazê-lo desta maneira:
Ou assim:
A
"some text here"
cadeia não pode ser extraída do símbolo, é apenas uma descrição para fins de depuração. Não muda o comportamento do símbolo de forma alguma. No entanto, você podeconsole.log
(o que é justo, já que o valor é para depuração, para não confundir esse log com outra entrada de log):2. Para obter um símbolo para alguns dados de string
Nesse caso, o valor do símbolo é realmente levado em consideração e, dessa forma, dois símbolos podem não ser exclusivos.
Vamos chamar esses símbolos de "segundo tipo". Eles não se cruzam com os símbolos do "primeiro tipo" (isto é, os definidos com
Symbol(data)
) de forma alguma.Os próximos dois parágrafos pertencem apenas ao símbolo do primeiro tipo .
Como me beneficio do uso do Symbol em vez dos tipos de dados mais antigos?
Vamos primeiro considerar um objeto, um tipo de dados padrão. Poderíamos definir alguns pares de valores-chave e ter acesso aos valores especificando a chave.
E se tivermos duas pessoas com o nome Peter?
Fazendo isso:
não faria muito sentido.
Portanto, parece ser um problema de duas pessoas absolutamente diferentes com o mesmo nome. Vamos então nos referir a novos
Symbol()
. É como uma pessoa na vida real - qualquer pessoa é única , mas seus nomes podem ser iguais. Vamos definir duas "pessoas".Agora temos duas pessoas diferentes com o mesmo nome. Nossas pessoas são realmente diferentes? Eles são; você pode verificar isso:
Como nos beneficiamos lá?
Podemos fazer duas entradas no seu objeto para as diferentes pessoas e elas não podem ser confundidas de forma alguma.
Usando esta inicialização, é absolutamente impossível confundir as entradas para a primeira e a segunda pessoas. Chamar
console.log
por eles produzirá corretamente seus segundos nomes.Quando usado no objeto, como ele é diferente em comparação à definição de propriedade não enumerável?
De fato, já existia uma maneira de definir uma propriedade a ser oculta
Object.keys
e enumerada. Aqui está:Que diferença
Symbol()
traz para lá? A diferença é que você ainda pode obter a propriedade definidaObject.defineProperty
da maneira usual:E se definido com o símbolo como no parágrafo anterior:
Você terá a capacidade de receber seu valor somente se conhecer sua variável, ou seja,
Além disso, definir outra propriedade sob a chave
"apple"
fará com que o objeto descarte a mais antiga (e, se for codificado, poderá gerar um erro). Então, não há mais maçãs! É uma pena. Referindo-se ao parágrafo anterior, os Símbolos são únicos e definem uma chave, oSymbol()
que a tornará única.Conversão e verificação de tipo
Ao contrário de outros tipos de dados, é impossível convertê-lo
Symbol()
em qualquer outro tipo de dados.É possível "criar" um símbolo com base no tipo de dados primitivo chamando
Symbol(data)
.Em termos de verificação do tipo, nada muda.
fonte
Aqui está como eu vejo isso. Os símbolos fornecem 'um nível extra de privacidade', impedindo que as chaves / propriedades de um objeto sejam expostas por alguns métodos populares, como Object.keys () e JSON.stringify ().
Embora dado um objeto em si, essas propriedades ainda possam ser expostas por meio de reflexão, proxy, Object.getOwnPropertySymbols () etc., não há meios naturais para acessá-los por meio de alguns métodos diretos, que às vezes podem ser suficientes da perspectiva de OOP.
fonte
Um símbolo JS é um novo tipo de dados primitivo. São tokens que servem como IDs únicos . Um símbolo pode ser criado usando o
Symbol
construtor. Tomemos, por exemplo, este trecho do MDN:Muitas vezes, é útil usar símbolos como chaves de propriedade de objeto exclusivas, por exemplo:
fonte
Fonte
fonte