Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Sessão 11 (Para saber mais: tipo Symbol) do módulo 03 (Tipos de Dados) do curso de JavaScript: utilizando tipos, variáveis e funções

Oi pessoal, tudo bem?

Na Sessão 11 do módulo 03, foi apresentado o tipo Symbol. Eu entendi que ele é um tipo elementar e que é utilizado para que seja possível proteger uma variável do código principal ou de possíveis alterações que possam utilizar essa mesma variável em outras partes do código. Conceitualmente eu entendi, porém, não ficou muito claro como ele é implementado (também entendi sobre a possibilidade de criar uma espécie de "alias" para a váriavel) e também gostaria de enxergar um caso de uso mais evidente em que essa categoria de tipo poderia ser usado.

Tentei ler alguns artigos pela internet para esclarecer, mas ainda não estou muito seguro.

Agradeço se alguém puder interagir com algum material sobre isso ou então me dar algum exemplo que exemplifique de maneira mais evidente.

Muitíssimo obrigado desde já!

Abraços

3 respostas

Oi, Rafael! Tudo bem?

Que legal que você está se aprofundando no tipo Symbol!

O tipo Symbol em JavaScript é utilizado para criar identificadores únicos. Isso é muito útil quando você quer garantir que uma propriedade de um objeto não conflite com outras propriedades, mesmo que tenham o mesmo nome. Vamos ver um exemplo:

// Criando Symbols
const sym1 = Symbol('descricao1');
const sym2 = Symbol('descricao2');

// Mesmo que a descrição seja a mesma, os Symbols são únicos
const sym3 = Symbol('descricao1');

console.log(sym1 === sym2); // false
console.log(sym1 === sym3); // false

// Usando Symbols como propriedades de um objeto
const meuObjeto = {
    [sym1]: 'Valor para sym1',
    [sym2]: 'Valor para sym2',
    nome: 'Objeto de exemplo'
};

console.log(meuObjeto[sym1]); // 'Valor para sym1'
console.log(meuObjeto[sym2]); // 'Valor para sym2'
console.log(meuObjeto.nome);  // 'Objeto de exemplo'

// Symbols não aparecem em loops de iteração padrão
for (let chave in meuObjeto) {
    console.log(chave); // Apenas 'nome' será exibido
}

// Mas você pode acessar as propriedades Symbol usando Object.getOwnPropertySymbols
const symbols = Object.getOwnPropertySymbols(meuObjeto);
console.log(symbols); // [ Symbol(descricao1), Symbol(descricao2) ]

Neste exemplo, criamos três Symbols, sendo dois com a mesma descrição. Mesmo assim, eles são únicos e não iguais (sym1 !== sym3). Em seguida, utilizamos esses Symbols como chaves de propriedades em um objeto. Note que ao iterar sobre o objeto com um for...in, as propriedades Symbol não aparecem, o que ajuda a proteger essas propriedades de modificações acidentais.

Um caso de uso comum para Symbols é quando você está desenvolvendo uma biblioteca ou framework e quer garantir que algumas propriedades internas não sejam sobrescritas ou acessadas diretamente pelo usuário da biblioteca.

Espero ter ajudado.

Um abraço e bons estudos.

Oi Lorena, tudo bem? Muito obrigado pela atenção e pelos exemplos. Ainda tenho algumas considerações, mas acho que ficou melhor ilustrado agora.

  1. No exemplo que você usa o symbol como uma chave para um objeto, você criou uma variável para representar todo o conteúdo do objeto e o Object.getOwnPropertySymbols traz os dois simbolos (ou todas as chaves) daquele objeto. Mas e se eu quiser acessar somente uma chave específica ou então um valor relacionado à uma chave. Visto que o os laços de repetição não entregam o conteúdo dos symbols, como eu poderia fazer para iterar sobre eles?
  2. Qual seria a diferença entre usar um símbolo para restringir o acesso externo e de declarar a variável como privada, ou então criar uma função (ou até uma classe) privada para que as variáveis não estejam expostas?
  3. Em complemento, no python, por exemplo, eu poderia usar o dunder para criar um magic method para deixar a função restrita à classe ou a função. É possível fazer algo semelhante no JS?

Novamente, muito obrigado pelo apoio!

Abraço!

solução!

Oii Rafael, tudo bem?

  • Acessar um Symbol específico Pra acessar um valor associado a um Symbol específico em um objeto, você pode utilizar a referência direta ao Symbol ou iterar sobre os Symbols do objeto:
const sym1 = Symbol('descricao1');
const sym2 = Symbol('descricao2');

const meuObjeto = {
    [sym1]: 'Valor para sym1',
    [sym2]: 'Valor para sym2',
    nome: 'Objeto de exemplo'
};

// Acessando diretamente
console.log(meuObjeto[sym1]); // 'Valor para sym1'

// Iterando sobre os Symbols
const symbols = Object.getOwnPropertySymbols(meuObjeto);
for (const sym of symbols) {
    console.log(`Chave: ${sym.toString()}, Valor: ${meuObjeto[sym]}`);
}
  • Diferença entre Symbols e variáveis privadas

Os Symbols são úteis pra criar chaves de propriedades únicas que não conflitam com outras propriedades do objeto, protegendo-as contra acesso e modificação não intencionais. Mas, as propriedades Symbol não são verdadeiramente privadas, pois podem ser acessadas com métodos apropriados como Object.getOwnPropertySymbols.

Já variáveis privadas (implementadas com a sintaxe # ou closures) são uma abordagem diferente para esconder detalhes de implementação.

Comparação com Python

JavaScript não possui uma sintaxe direta equivalente ao "dunder" de Python, mas a introdução de campos privados com # oferece um nível similar de encapsulamento.

Então:

  • Symbols: Úteis para criar propriedades únicas em objetos que não interferem umas com as outras e não são expostas diretamente em loops de iteração padrão. São acessíveis com métodos específicos.
  • Campos privados: Proporcionam encapsulamento verdadeiro, não podendo ser acessados ou modificados diretamente de fora da classe ou função.

Espero que isso esclareça as diferenças e te ajude a entender melhor como e quando usar Symbols e outras técnicas de encapsulamento em JavaScript.

Abraços e bons estudos.