Resumo : neste tutorial, você aprenderá sobre o tipo primitivo de símbolo JavaScript e como usá-lo de maneira eficaz.
Criando símbolos
ES6 adicionado Symbol
como um novo tipo primitivo. Ao contrário de outros tipos primitivos, como number , boolean , null , undefined e string , o tipo de símbolo não possui uma forma literal.
Para criar um novo símbolo, você usa a Symbol()
função global conforme mostrado neste exemplo:
let s = Symbol('foo');
Linguagem de código: JavaScript ( javascript )
A Symbol()
função cria um novo valor exclusivo cada vez que você a chama:
console.log(Symbol() === Symbol()); // false
Linguagem de código: JavaScript ( javascript )
A Symbol()
função aceita a description
como argumento opcional. O description
argumento tornará seu símbolo mais descritivo.
O exemplo a seguir cria dois símbolos: firstName
e lastName
.
let firstName = Symbol('first name'),
lastName = Symbol('last name');
Linguagem de código: JavaScript ( javascript )
Você pode acessar a propriedade de descrição do símbolo usando o toString()
método. O console.log()
método chama o toString()
método do símbolo implicitamente, conforme mostrado no exemplo a seguir:
console.log(firstName); // Symbol(first name)
console.log(lastName); // Symbol(last name)
Linguagem de código: JavaScript ( javascript )
Como os símbolos são valores primitivos, você pode usar o typeof
operador para verificar se uma variável é um símbolo. ES6 estendido typeof
para retornar a symbol
string quando você passa uma variável de símbolo:
console.log(typeof firstName); // symbol
Linguagem de código: JavaScript ( javascript )
Como um símbolo é um valor primitivo, se você tentar criar um símbolo usando o new
operador, receberá um erro:
let s = new Symbol(); // error
Linguagem de código: JavaScript ( javascript )
Compartilhando símbolos
ES6 fornece um registro de símbolos global que permite compartilhar símbolos globalmente. Se você deseja criar um símbolo que será compartilhado, use o Symbol.for()
método em vez de chamar a Symbol()
função.
O Symbol.for()
método aceita um único parâmetro que pode ser utilizado para descrição do símbolo, conforme exemplo a seguir:
let ssn = Symbol.for('ssn');
Linguagem de código: JavaScript ( javascript )
O Symbol.for()
método primeiro procura o símbolo com a ssn
chave no registro global de símbolos. Ele retorna o símbolo existente, se houver. Caso contrário, o Symbol.for()
método cria um novo símbolo, registra-o no registro global de símbolos com a chave especificada e retorna o símbolo.
Posteriormente, se você chamar o Symbol.for()
método usando a mesma chave, o Symbol.for()
método retornará o símbolo existente.
let citizenID = Symbol.for('ssn');
console.log(ssn === citizenID); // true
Linguagem de código: JavaScript ( javascript )
Neste exemplo, usamos o Symbol.for()
método para procurar o símbolo com a ssn
chave. Como o registro global de símbolos já o continha, o Symbol.for()
método retornou o símbolo existente.
Para obter a chave associada a um símbolo, você usa o Symbol.keyFor()
método mostrado no exemplo a seguir:
console.log(Symbol.keyFor(citizenID)); // 'ssn'
Linguagem de código: JavaScript ( javascript )
Se um símbolo não existir no registro global de símbolos, o System.keyFor()
método retornará undefined
.
let systemID = Symbol('sys');
console.log(Symbol.keyFor(systemID)); // undefined
Linguagem de código: JavaScript ( javascript )
Usos de símbolos
A) Usando símbolos como valores únicos
Sempre que você usar uma string ou um número em seu código, você deve usar símbolos. Por exemplo, você precisa gerenciar o status no aplicativo de gerenciamento de tarefas.
Antes do ES6, você usaria strings como open
, in progress
, completed
, canceled
e on hold
para representar diferentes status de uma tarefa. No ES6, você pode usar símbolos da seguinte forma:
let statuses = {
OPEN: Symbol('Open'),
IN_PROGRESS: Symbol('In progress'),
COMPLETED: Symbol('Completed'),
HOLD: Symbol('On hold'),
CANCELED: Symbol('Canceled')
};
// complete a task
task.setStatus(statuses.COMPLETED);
Linguagem de código: JavaScript ( javascript )
B) Usando um símbolo como o nome da propriedade computada de um objeto
Você pode usar símbolos como nomes de propriedades computadas . Veja o exemplo a seguir:
let status = Symbol('status');
let task = {
[status]: statuses.OPEN,
description: 'Learn ES6 Symbol'
};
console.log(task);
Linguagem de código: JavaScript ( javascript )
Para obter todas as propriedades enumeráveis de um objeto, você usa o Object.keys()
método.
console.log(Object.keys(task)); // ["description"]
Linguagem de código: JavaScript ( javascript )
Para obter todas as propriedades de um objeto, sejam elas enumeráveis ou não, você usa o Object.getOwnPropertyNames()
método.
console.log(Object.getOwnPropertyNames(task)); // ["description"]
Linguagem de código: JavaScript ( javascript )
Para obter todos os símbolos de propriedades de um objeto, você usa o Object.getOwnPropertySymbols()
método, que foi adicionado no ES6.
console.log(Object.getOwnPropertySymbols(task)); //[Symbol(status)]
Linguagem de código: JavaScript ( javascript )
O Object.getOwnPropertySymbols()
método retorna uma matriz de símbolos de propriedades próprias de um objeto.
Símbolos conhecidos
ES6 fornece símbolos predefinidos que são chamados de símbolos bem conhecidos. Os símbolos conhecidos representam os comportamentos comuns em JavaScript. Cada símbolo conhecido é uma propriedade estática do Symbol
objeto.
Símbolo.hasInstance
O Symbol.hasInstance
é um símbolo que altera o comportamento do instanceof
operador. Normalmente, quando você usa o instanceof
operador:
obj instanceof type;
Linguagem de código: JavaScript ( javascript )
JavaScript chamará o Symbol.hasIntance
método da seguinte maneira:
type[Symbol.hasInstance](obj);
Linguagem de código: JavaScript ( javascript )
Depende então do método para determinar se obj
é uma instância do type
objeto. Veja o exemplo a seguir.
class Stack {
}
console.log([] instanceof Stack); // false
Linguagem de código: JavaScript ( javascript )
O []
array não é uma instância da Stack
classe, portanto, o instanceof
operador retorna false
neste exemplo.
Supondo que você queira que o []
array seja uma instância da Stack
classe, você pode adicionar o Symbol.hasInstance
método da seguinte forma:
class Stack {
static [Symbol.hasInstance](obj) {
return Array.isArray(obj);
}
}
console.log([] instanceof Stack); // true
Linguagem de código: JavaScript ( javascript )
Símbolo.iterador
Especifica Symbol.iterator
se uma função retornará um iterador para um objeto.
Os objetos que possuem Symbol.iterator
propriedade são chamados de objetos iteráveis.
No ES6, todos os objetos de coleção (A rray , Set e Map ) e strings são objetos iteráveis.
ES6 fornece o loop for…of que funciona com o objeto iterável como no exemplo a seguir.
var numbers = [1, 2, 3];
for (let num of numbers) {
console.log(num);
}
// 1
// 2
// 3
Linguagem de código: JavaScript ( javascript )
Internamente, o mecanismo JavaScript primeiro chama o Symbol.iterator
método do array de números para obter o objeto iterador.
Em seguida, ele invoca o iterator.next()
método e copia a propriedade value do objeto iterador para a num
variável.
Após três iterações, a done
propriedade do objeto de resultado é true
, o loop termina.
Você pode acessar o objeto iterador padrão via System.iterator
símbolo da seguinte forma:
var iterator = numbers[Symbol.iterator]();
console.log(iterator.next()); // Object {value: 1, done: false}
console.log(iterator.next()); // Object {value: 2, done: false}
console.log(iterator.next()); // Object {value: 3, done: false}
console.log(iterator.next()); // Object {value: undefined, done: true}
Linguagem de código: JavaScript ( javascript )
Por padrão, uma coleção não é iterável. No entanto, você pode torná-lo iterável usando Symbol.iterator
conforme mostrado no exemplo a seguir:
class List {
constructor() {
this.elements = [];
}
add(element) {
this.elements.push(element);
return this;
}
*[Symbol.iterator]() {
for (let element of this.elements) {
yield element;
}
}
}
let chars = new List();
chars.add('A')
.add('B')
.add('C');
// because of the Symbol.iterator
for (let c of chars) {
console.log(c);
}
// A
// B
// C
Linguagem de código: JavaScript ( javascript )
Símbolo.isConcatSpreadable
Para concatenar dois arrays, você usa o concat()
método mostrado no exemplo a seguir:
let odd = [1, 3],
even = [2, 4];
let all = odd.concat(even);
console.log(all); // [1, 3, 2, 4]
Linguagem de código: JavaScript ( javascript )
Neste exemplo, a matriz resultante contém os elementos únicos de ambas as matrizes. Além disso, o concat()
método também aceita um argumento que não seja de array, conforme ilustrado abaixo.
let extras = all.concat(5);
console.log(extras); // [1, 3, 2, 4, 5]
Linguagem de código: JavaScript ( javascript )
O número 5 se torna o quinto elemento da matriz.
Como você pode ver no exemplo acima, quando passamos um array para o concat()
método, o concat()
método espalha o array em elementos individuais. No entanto, trata um único argumento primitivo de forma diferente. Antes do ES6, não era possível alterar esse comportamento.
É por isso que o Symbol.isConcatSpreadable
símbolo entra em jogo.
A Symbol.isConcatSpreadable
propriedade é um valor booleano que determina se um objeto é adicionado individualmente ao resultado da concat()
função.
Considere o seguinte exemplo:
let list = {
0: 'JavaScript',
1: 'Symbol',
length: 2
};
let message = ['Learning'].concat(list);
console.log(message); // ["Learning", Object]
Linguagem de código: JavaScript ( javascript )
O objeto de lista é concatenado ao ['Learning']
array. No entanto, os seus elementos individuais não estão dispersos.
Para habilitar os elementos do list
objeto adicionados ao array individualmente ao passar para o concat()
método, você precisa adicionar a Symbol.isConcatSpreadable
propriedade ao list
objeto da seguinte forma:
let list = {
0: 'JavaScript',
1: 'Symbol',
length: 2,
[Symbol.isConcatSpreadable]: true
};
let message = ['Learning'].concat(list);
console.log(message); // ["Learning", "JavaScript", "Symbol"]
Linguagem de código: JavaScript ( javascript )
Observe que se você definir o valor de Symbol.isConcatSpreadable
to false
e passar o list
objeto para o concat()
método, ele será concatenado ao array como o objeto inteiro.
Símbolo.toPrimitivo
O Symbol.toPrimitive
método determina o que deve acontecer quando um objeto é convertido em um valor primitivo.
O mecanismo JavaScript define o Symbol.toPrimitive
método no protótipo de cada tipo padrão.
O Symbol.toPrimitive
método aceita um hint
argumento que possui um de três valores: “número”, “string” e “padrão”. O hint
argumento especifica o tipo do valor de retorno. O hint
parâmetro é preenchido pelo mecanismo JavaScript com base no contexto em que o objeto é utilizado.
Aqui está um exemplo de uso do Symbol.toPrimitive
método.
function Money(amount, currency) {
this.amount = amount;
this.currency = currency;
}
Money.prototype[Symbol.toPrimitive] = function(hint) {
var result;
switch (hint) {
case 'string':
result = this.amount + this.currency;
break;
case 'number':
result = this.amount;
break;
case 'default':
result = this.amount + this.currency;
break;
}
return result;
}
var price = new Money(799, 'USD');
console.log('Price is ' + price); // Price is 799USD
console.log(+price + 1); // 800
console.log(String(price)); // 799USD
Linguagem de código: JavaScript ( javascript )
Neste tutorial, você aprendeu sobre símbolos JavaScript e como usar símbolos para valores exclusivos e propriedades de objetos. Além disso, você aprendeu como usar símbolos conhecidos para modificar o comportamento dos objetos.