ECMAScript 2015: Symbols

ES2015 Gotchas é uma série quinzenal sobre as novidades e pegadinhas do ES2015.

Symbol é o mais novo tipo primitivo disponível, único e imutável, que também pode ser usado como identificador para acessar propriedades de um objeto. Mais importante do que o novo tipo em si, é o motivo pelo qual foi criado e como ele pode ser útil para você no dia a dia, mas antes disso precisamos ter certeza que entendemos o básico.

A criação de nosso novo amigo foi encapsulada em um objeto, que pode receber como parâmetro uma descrição opcional, mas que independente dela sempre retornara um novo e único symbol, mesmo que ela se repita, ou seja:

Symbol("key") !== Symbol("key")  

A descrição opcional serve apenas para leitura e depuração de código, podendo ser visualizada toda vez que uma execução pausada for inspecionada ou se o symbol for logado no console.

Existem também símbolos compartilhados, que ficam disponíveis em um registro global, a partir de uma chave que também será usado como descrição para debug. Caso ainda não exista um símbolo para a chave utilizada, ele será criado e ficara disponível para as próximas chamadas com a mesma.

Symbol.for("key") === Symbol.for("key")  
Symbol.for("key") !== Symbol("key")  

Propriedades privadas, ou quase isso

Ao ser utilizado como chave para acessar propriedades em objetos, estas propriedades não são listadas a partir dos métodos atuais de reflection disponíveis, e por serem sempre únicos, somente alguém com acesso ao símbolo original teria acesso a elas, o que as tornariam propriedades completamente privadas. Porem um novo método de reflection foi adicionado nessa especificação, Object.getOwnPropertySymbols, que retorna uma lista iterável de todas as propriedades criadas com symbols.

Veja o exemplo abaixo:

var privateProp = Symbol("myPrivate");

var obj = {  
  normalMethod : function(){ return "normal" },
  [privateProp]: function(){ return "symbol" }
}

console.log(Object.keys(obj));  
// [ 'normalMethod' ]

console.log(Object.getOwnPropertySymbols(obj));  
// [ Symbol(myPrivate) ]

console.log(obj[privateProp]());  
// symbol

Implementando features do ES2015

Este é o principal motivo pela qual os símbolos foram implementados na sexta versão do EcmaScript: como adicionar novas features aos objetos atuais, onde precisamos adicionar novas propriedades neles, sem quebrar os códigos sendo executados atualmente que não estão contando com essas novas novidades, e com isso quebrar a internet de uma hora para outra?

Fácil! Basta criar um novo método de criação de propriedades privados, ou quase, que não sejam listadas por nenhum método atual! Parece com algo que estejamos falando até agora?

Symbol.iterator  
Symbol.match  
Symbol.species  

Para cada nova feature que altere os objetos atuais existe um símbolo correspondente, listado como uma propriedade no objeto que encapsula a criação de novos symbols, como pode ser visto acima.

Eles também podem ser utilizado por nós em nosso próprio código, e assim podemos, por exemplo, customizar a iteração de nossos objetos dentro de um looping de for...of do ES2015:

var obj = {  
  [Symbol.iterator]: function*(){
    yield 1;
    yield 2;
    yield 3;
  }
}

for(let i of obj) console.log(i);  
// 1
// 2
// 3

Até a próxima! Fiquem ligados na série ES2015 Gotchas!

William Grasel

Read more posts by this author.