Objetos imutáveis em JS
Tags: javascript, beginners, braziliandevs
Published: 2023-01-09 19:06:24

> Este post é apenas uma nota sobre a postagem em [JSTips](https://www.jstips.co/en/javascript/creating-immutable-objects-in-native-javascript/) e a thread do [Felippe Regazio](https://twitter.com/FelippeRegazio/status/1605261971758387200) acerca do tópico.

Para iniciar é importante entender que objetos imutáveis referem-se à objetos que não devem ser modificados. Ou seja, após a criação o objeto passa a ter propriedade de apenas leitura.

Vejamos o objeto abaixo, onde possui informações de redes sociais, após a criação não é possível alterar `SocialMedia`, porém é possível alterar as informações internas - assim como inserir novas.

```javascript
const SocialMedia = {
  'dev.to': 'https://dev.to/netojocelino',
  'github': 'https://github.com/netojocelino',
  'linkedin': 'https://www.linkedin.com/in/netojocelino',
  'snippets': 'https://gist.github.com/netojocelino',
}
```

Caso tente modificar o valor de `SocialMedia`, como  `SocialMedia = null`, o erro abaixo será lançado
`Uncaught TypeError: invalid assignment to const 'SocialMedia'`.

Para tornar objetos mais restritivos à edição, também é possível adicionar prevenção à extensões, ou seja, adição de novas propriedades.

Desta forma, imaginemos o mesmo objeto. Porém, após a criação adiciona-se uma restrição à adição de novas propriedades, não gerando erro para criar, porém não insere uma nova propriedade.

```javascript
const SocialMedia = {
  'dev.to': 'https://dev.to/netojocelino',
  'github': 'https://github.com/netojocelino',
  'linkedin': 'https://www.linkedin.com/in/netojocelino',
  'snippets': 'https://gist.github.com/netojocelino',
} // { 'dev.to': '...', 'github': '...', 'linkedin': '...', 'snippets': '...' }

Object.preventExtensions(SocialMedia)

SocialMedia.gitlab = 'https://gitlab.com/netojocelino' // { 'dev.to': '...', 'github': '...', 'linkedin': '...', 'snippets': '...' } 
```

É importante notar que ainda será possível editar ou remover alguma propriedade já existente.
Assim, caso seja utilizado o trecho `SocialMedia.snippets = 'https://codepen.io/netojocelino/pens'` o objeto será modificado, e caso remova uma propriedade com `delete SocialMedia['dev.to']` ainda surtirá efeito.

```javascript
// { 'github': '...', 'linkedin': '...', 'snippets': 'https://codepen.io/netojocelino/pens' }
```

Para prevenir modificações como edição ou remoção é possível utilizar `Object.seal(SocialMedia)`. 
Desta forma, caso tenha tentativa de edição, `SocialMedia.snippets = 'https://codepen.io/netojocelino/pens'` ou remoção `delete SocialMedia['dev.to']` o objeto não será alterado.

```javascript
// { 'dev.to': '', 'github': '...', 'linkedin': '...', 'snippets': '...' }
```

Para bloquear também as adições, é necessário utilizar `Object.freeze(SocialMedia)`, que bloqueia tanto a remoção, edição e também a adição de novas propriedades, fazendo `SocialMedia.telegram = 'https://t.me/netojocelino'` não ser adicionado ao objeto, mantendo  a estrutura de

```javascript
// { 'dev.to': '', 'github': '...', 'linkedin': '...', 'snippets': '...' }
```


Todas estas propriedades podem ser checadas, de forma que `Object.isExtensible(SocialMedia)` retorna um booleano `true` caso seja possível adicionar novas propriedades no objeto e `false` caso não possa ser extensível. O retorno de `Object.isSealed(SocialMedia)` retorna `true` quando é prevenido a adição ou remoção de propriedades do objeto e `false` quando é possível adicionar ou remover. O método `Object.isFrozen(SocialMedia)` indica caso não for possível alterar de forma alguma alguma propriedade.




Resumo:

- Mesmo um objeto definido como constante pode sofrer algum tipo de mutação interna.
- É possível restringir adição de novas propriedades com `Object.preventExtensions(myObject)`. Para conferir se está com restrição, use `Object.isExtensible(myObject)` (`true` para bloqueado a adição).
- É possível restringir edição e remoção de propriedades com `Object.seal(myObject)`. Para conferir se está com restrição, use `Object.isSealed(myObject)` (`true` para bloqueado a edição e remoção). 
- É possível restringir adição, edição e remoção de propriedades com `Object.freeze(myObject)`. Para conferir se está com restrição, use `Object.isFrozen(myObject)` (`true` para bloqueado qualquer manipulação).