Atualizações de matriz imutável com Array.prototype.with

Recentemente, os navegadores ganharam um novo método interoperável que pode ser chamado em matrizes: Array.prototype.with().

Compatibilidade com navegadores

  • 110
  • 110
  • 115
  • 16

Origem

Este artigo explica como esse método funciona e como usá-lo para atualizar uma matriz sem modificar a original.

Introdução ao curso Array.prototype.with(index, value)

O método Array.prototype.with(index, value) retorna uma cópia da matriz em que é chamada com o index definido como o novo value fornecido.

O exemplo abaixo mostra uma matriz de idades. Você gostaria de criar uma nova cópia da matriz enquanto altera a segunda idade de 15 para 16:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

Detalhamento do código: ages.with(...) retorna uma cópia da variável ages sem modificar a matriz original. ages.with(1, …) substitui o segundo item (index = 1). ages.with(1, 16) atribui o segundo item a 16.

Dessa forma, você conseguiu criar uma nova cópia da matriz com uma modificação.

Isso é muito útil quando você quer garantir que a matriz original permaneça inalterada. Este artigo aborda alguns dos casos de uso para isso. Mas, por enquanto, dê uma olhada no que teria acontecido se você tivesse usado a notação de colchete:

const ages = [10, 15, 20, 25];

const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)

Como você pode notar, a variável ages também foi modificada neste exemplo. Isso ocorre porque, quando você atribui ages = newAges, o JavaScript não copia a matriz, mas cria uma referência para a outra matriz. Portanto, qualquer alteração em uma também afeta a outra, porque ambas apontam para a mesma matriz.

Array.prototype.with() e imutabilidade

A imutabilidade está no centro de muitas bibliotecas e frameworks de front-end, entre outros: React (e redux) e Vue.

Além disso, outras bibliotecas e frameworks não exigem necessariamente imutabilidade, mas incentivam essa funcionalidade para um melhor desempenho: Angular e Lit.

Assim, muitas vezes, os desenvolvedores precisavam usar outros métodos que retornavam cópias de matrizes, o que sacrificava a legibilidade do código:

const ages = [10, 15, 20, 25];

const newAges = ages.map((age, index) => {
    if (index === 1) {
         return 16;
    }
    return age;
});

console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)

Confira um exemplo do Codepen de como o .with() pode ser usado no React em combinação com useState para atualizar de forma imutável uma matriz de itens:

Como o método .with() retorna uma cópia da matriz, você pode encadear várias chamadas .with() ou até mesmo outros métodos de matriz. O exemplo a seguir demonstra como incrementar a segunda e a terceira idades a partir da matriz:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)

console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

Outros métodos novos imutáveis

Outros três métodos tornaram-se interoperáveis recentemente:

De acordo com o MDN, esses três métodos são a versão com cópia das equivalentes. Esses métodos também podem ser usados quando a imutabilidade é esperada ou preferida.

Em resumo, as atualizações imutáveis podem ser feitas mais facilmente em JavaScript com um dos quatro métodos apresentados neste artigo. Especificamente, o método .with() facilita a atualização de um único elemento da matriz sem modificar a matriz original.