JavaScript: O que é Symbol?
Tags: javascript, braziliandevs, beginners, node
Published: 2024-06-19 14:28:32

Eae gente bonita, beleza? Continuo a jornada de "aprofundamento" em JavaScript e quanto mais eu aprendo mais eu quero escrever e compartilhar com vocês. Dessa vez vou falar um pouco sobre o ``Symbol`` que para mim o motivo da sua existência sempre foi um mistério.

![Misterio gif](https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExbjFtM3hlNmZyejRyb2Ixa25uM3E0ZzN4dnkxZ3AxYnVoZGpsY2JtdyZlcD12MV9naWZzX3NlYXJjaCZjdD1n/3oEjHSuTCk0TBeLcGs/giphy.gif)


## Tabela de conteúdos

* [O que é Symbol](#o-que-é-symbol)
* [Criando propriedades "privadas"](#criando-propriedades-privadas)
* [Mas por que "privado"](#mas-por-que-privado)
* [Symbols e comportamentos padrão](#symbols-e-comportamentos-padrão)
* [Referências](#referências)


## O que é Symbol

Começando do começo, o Symbol é um tipo primitivo no JavaScript, ele é usado para criar valores, funções privadas e até mesmo para interceptar um comportamento padrão de um objeto no JavaScript. 

> Mas não se esqueça de uma coisa, no JavaScript TUDO é objeto.

Apenas para confirmar que o symbol é um tipo primitivo

```javascript
typeof Symbol("foo") === "symbol"; // true
```

## Criando propriedades "privadas"

Com o Symbol podemos criar algumas propriedades quase privadas. Abaixo um exemplo

```javascript
const uniqueKey = Symbol("userName");
const user = {};

user["userName"] = "value normal object";
user[uniqueKey] = "value from symbol";
console.log('getting object', user[uniqueKey]); // "value from symbol"
console.log('getting object', user["userName"]); // "value normal object"
console.log('getting object', user[Symbol("userName")]); // undefined
```

No exemplo nós criamos a `uniqueKey `com o `Symbol `com o valor `userName` e um objeto `user`. Primeiro colocamos um valor na propriedade `user["userName"]` e depois fazemos a mesma coisa com a propriedade `user[uniqueKey]` e você pode pensar, bom o symbol tem o mesmo valor que é userName, então o valor foi sobrescrito mas na verdade não. O Symbol cria um outro endereço de memória e uma propriedade diferente.
Ok, então se eu criar um Symbol com o mesmo valor eu consigo acessar? Errado novamente. Como disse o Symbol cria um novo endereço na memória logo o terceiro console log retorna undefined. Por isso que com ele nós podemos criar variáves e métodos privados, pois os mesmos só serão acessados se o Symbol usado for exportado junto.

## Mas por que "privado"

Bom imagino que deve ter percebido o uso excessivo das aspas em privado isso acontece porque nós podemos saber quais são o symbols existentes. Vamos a mais um exemplo:

```javascript
const uniqueKey = Symbol("userName");
const func = Symbol("soma");
const user = {};

user[uniqueKey] = "value from symbol";
user[func] = (n1, n2) => n1+ n2;

console.log('symbols', Object.getOwnPropertySymbols(user));// symbols [ Symbol(userName), Symbol(soma) ]

```

Como podemos ver no exemplo acima os Symbols desse objeto não são privados. Com um simples método do `Object` nós podemos ver o Symbols existentes, porém não podemos acessá-los ou ler suas implementações.

## Symbols e comportamentos padrão

Com o Symbol nós podemos alterar alguns comportamentos padrão dos objetos, como por exemplo como um objeto será lido por uma função de iterator ou convertido para string.

Vamos aos exemplos!

```javascript
const obj = {
    items: ['c', 'b', 'a'],
}
```

Para podermos ler o objeto acima em um iterator(for, forEach, map) nós precisariamos usar alguma função como Objeto.entries ou Object.keys para transformar as chaves em um array e ler propriedade por propriedade.

Mas e se quiséssemos que esse objeto fosse lido de forma correta por um iterator? Bom nós podemos mudar esse comportamento, como no exemplo abaixo

```javascript
const obj = {
    [Symbol.iterator]: () => ({
        items: ['c', 'b', 'a'],
        next() {
            return {
                done: this.items.length === 0,
                value: this.items.pop()
            }
        }
    })
}
```

Dessa forma podemos apenas chamar uma função de iterator e o nosso objeto será lido sem problema algum. O mesmo vale para `toString` por exemplo e por ai vai. Caso queira saber recomendo pesquisar sobre prototypes no JavaScript.


## Referências

[Symbol - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)

-------

Espero que tenha sido claro e tenha ajudado a entender um pouco mais sobre o assunto, fique a vontade para dúvidas e sugestões abaixo!

Se chegou até aqui, me segue la nas [redes vizinhas]
(https://cristiansilva.dev/).

<img src="https://media.giphy.com/media/xULW8v7LtZrgcaGvC0/giphy.gif" alt="thank you dog" />