JavaScript ES6 Symbol como nome de propriedade
Don’t program by coincidence
— The Pragmatic Programmer, Andrew Hunt e David Thomas
Durante uma aula do Willian Justen sobre ES6, ele colocou um Symbol (veja também ES6 In Depth: Symbols) entre colchetes para usá-lo como key de um objeto definido por meio da sintaxe object literals. Por que exatamente foi necessário? O código era mais ou menos assim:
let foo = Symbol('name')
let obj = {
[foo]: 'value'
}
O que [foo]
significa? Resolvi entender precisamente como esses conceitos básicos funcionam—em vez de aceitá-los como faço às vezes :)
Object literals e as keys de um objeto
Object literals é uma sintaxe usada para definir objetos em JavaScript. É basicamente uma lista de key:value
envolvida por chaves { }
. A key também pode ser entendida como o nome de uma propriedade de um objeto.
let myObj = {
name: 'Thiago Colares',
city: 'Salvador'
}
Mas é importante entender que na sintaxe acima a chave precisa ser uma string válida. Se não for, o JavaScript tentará transformar a chave em string (fazendo typecast usando .toString) e só. Resultado:
let bar = Symbol('name')
let obj = {
bar: true, // a key será a string 'bar', não o Symbol bar!
123: true, // a key será a string '123'
'oxe': true, // a key será a string 'oxe'
}
Keys de objetos não são feitas só de string
O ECMAScript 2015 introduziu a funcionalidade computed property names. Assim, toda key definida entre colchetes [ ]
terá seu valor computado. Pode ser uma expressão, objeto, Symbol etc. Olhe:
let person = {name: 'Thiago Colares', city: 'Salvador'}
let bar = Symbol('name')
let nick = "colares"
let obj = {
bar: true, // a key será ‘bar’
[bar]: true, // a key será o Symbol bar
123: true, // a key será '123'
'oxe': true, // a key será 'oxe'
[10 + 40]: true, // a key será '50'
[`I'm ${nick}`]: true, // a key será "I'm colares"
[person]: true, // a key será o objeto person
[bomb]: true, // Uncaught ReferenceError: bomb is not defined
}
Note que se você usar uma palavra não definida dentro do [ ]
, um erro será retornado: Uncaught ReferenceError: bomb is not defined
.
Conclusões
[ ]
foi usado para interpretar a palavra bar como o Symbol definido anteriormente — em vez de transforma-la na string ‘bar’;- É possível usar Symbol como key de um objeto — spoiler: ele não é enumerável e, portanto, tem comportamentos diferentes das string keys;
- Recomendo ler sobre Symbols, um novo tipo de dado primitivo introduzido no ES6. É imutável, único e é muito útil.
No fim das contas, esse código:
let bomb = 'tnt'
let boom = {
[tnt]: true
}
É só um syntax sugar, ou melhor, açúcar sintático para:
let bomb = 'tnt'
let boom = {}
boom[tnt] = true
Veja mais sobre a notação com ponto ou colchete para acessar ou definir propriedades de um objeto.