Mutável e Imutável em JavaScript

Mutável e Imutável em JavaScript

Este artigo explica os conceitos de mutável e imutável em JavaScript.

YouTube Video

Mutável e Imutável em JavaScript

O que é Mutável?

Mutável significa que um valor pode ser modificado. Objetos e arrays, que são tipos por referência, são exemplos típicos de estruturas de dados mutáveis.

Exemplo de um Objeto Mutável

1let person = { name: "Alice", age: 25 };
2person.age = 26;
3console.log(person); // { name: "Alice", age: 26 }

Neste código, a propriedade age do objeto person é alterada de 25 para 26. Como os objetos são passados por referência, o conteúdo no endereço de memória armazenado na variável person é modificado.

Exemplo de um Array Mutável

1let numbers = [1, 2, 3];
2numbers.push(4);
3console.log(numbers); // [1, 2, 3, 4]

Neste código, o método push é usado para adicionar um novo elemento 4 ao array original. Isso modifica o array original, tornando-a uma operação mutável.

Exemplo em uma Função

 1// Function to append a value to an array
 2function append(arr, value) {
 3    arr.push(value); // Modify the original array
 4    console.log(arr);
 5}
 6
 7let numbers = [1, 2, 3];
 8append(numbers, 4);
 9
10console.log(numbers); // [1, 2, 3, 4] (original array is modified)

Ao realizar operações mutáveis dentro de uma função, o array original também é modificado.

O que é Imutável?

Imutável significa que um valor não pode ser modificado. Tipos primitivos são fundamentalmente imutáveis.

Exemplo de um Tipo Primitivo Imutável

1let str = "hello";
2str[0] = "H";
3console.log(str); // "hello"

Tentar alterar o primeiro caractere da string str para H falha porque strings são imutáveis.

Exemplo em uma Função

 1// Function to increment a number
 2function increment(num) {
 3    num++; // This modifies only the local copy of num
 4    console.log(num);
 5}
 6
 7let number = 10;
 8increment(number);
 9
10console.log(number); // 10 (original number remains unchanged)

Como os números são imutáveis, operações dentro de uma função não afetam a variável original.

Operações Imutáveis em Arrays

Arrays são mutáveis, mas criar um novo array em vez de modificar o original permite operações imutáveis.

1// Create an array of numbers
2let numbers = [1, 2, 3];
3
4// Create a new array by spreading the original and adding a new element
5let newNumbers = [...numbers, 4];
6
7console.log(numbers); // [1, 2, 3] (original array is unchanged)
8console.log(newNumbers); // [1, 2, 3, 4] (new array with an added element)

Aqui, a sintaxe de espalhamento (...) é usada para criar um novo array newNumbers. Como o array original numbers não é modificado, esta é uma operação imutável.

Benefícios de Usar Estruturas de Dados Imutáveis

Maior Previsibilidade

Como os dados imutáveis não podem ser alterados, modificações inesperadas são menos prováveis, reduzindo o risco de erros.

Compatibilidade com Bibliotecas Baseadas em Imutabilidade

Bibliotecas como React e Redux são frequentemente projetadas com dados imutáveis em mente, tornando o gerenciamento de estado mais fácil quando usadas corretamente.

Tornando Objetos Imutáveis com Object.freeze

Object.freeze pode ser usado para evitar modificações em um objeto.

1// Create a frozen object (properties cannot be modified)
2const person = Object.freeze({ name: "Alice", age: 25 });
3
4// Attempt to modify a property (ignored in non-strict mode, error in strict mode)
5person.age = 26;
6
7console.log(person); // { name: "Alice", age: 25 }

No entanto, Object.freeze realiza um congelamento superficial, o que significa que as propriedades de objetos aninhados permanecem mutáveis.

1// Create a frozen object with a nested object
2const user = Object.freeze({ profile: { name: "Bob" } });
3
4// Attempt to modify a nested property (this works because Object.freeze() is shallow)
5user.profile.name = "Charlie";
6
7console.log(user.profile.name); // "Charlie" (nested object is still mutable)

Para criar um objeto totalmente imutável, é necessário um congelamento profundo.

 1// Function to deeply freeze an object, making all nested objects immutable
 2function deepFreeze(obj) {
 3  Object.keys(obj).forEach(key => {
 4    if (typeof obj[key] === "object" && obj[key] !== null) {
 5      deepFreeze(obj[key]); // Recursively freeze nested objects
 6    }
 7  });
 8  return Object.freeze(obj); // Freeze the top-level object
 9}
10
11// Create a deeply frozen object
12const user = deepFreeze({ profile: { name: "Bob" } });
13
14// Attempt to modify a nested property (ignored)
15user.profile.name = "Charlie";
16
17console.log(user.profile.name); // "Bob" (unchanged due to deep freeze)

Resumo

  • Dados mutáveis podem ser modificados, incluindo objetos e arrays.
  • Dados imutáveis não podem ser modificados, incluindo tipos primitivos como strings e números.
  • Usar a sintaxe de espalhamento ou map permite operações de dados imutáveis..
  • Object.freeze e deepFreeze podem ser usados para evitar modificações em objetos.
  • O uso de dados imutáveis permite um código mais previsível e com menos propensão a erros.

O design imutável melhora a segurança e a legibilidade do código, então faça bom uso dele!

Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.

YouTube Video