Os navegadores ganharam recentemente um novo método interoperável que pode ser chamado em matrizes:
Array.prototype.with().
Neste artigo, explicamos como esse método funciona e como usá-lo para atualizar uma matriz sem alterar a matriz original.
Introdução ao Array.prototype.with(index, value)
O método Array.prototype.with(index, value) retorna uma cópia da matriz em que ele é
chamado com o index definido como o novo value fornecido.
O exemplo a seguir mostra uma matriz de idades. Você quer criar uma nova cópia da matriz e mudar 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)
Analisando o 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.
Assim, 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, e este artigo aborda alguns dos casos de uso para isso. Mas, por enquanto, veja o que teria acontecido se você tivesse usado a notação de colchetes:
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 ver, a variável ages também foi modificada neste exemplo. Isso acontece porque, quando você atribui ages = newAges, o JavaScript não copia a matriz, mas cria uma referência à outra matriz. Portanto, qualquer mudança em um também vai afetar o outro, já que ambos apontam para a mesma matriz.
Array.prototype.with() e imutabilidade
A imutabilidade está no centro de muitas bibliotecas e frameworks de front-end, como React (e redux) e Vue.
Além disso, outras bibliotecas e frameworks não exigem necessariamente imutabilidade, mas a incentivam para melhorar o desempenho: Angular e Lit.
Por isso, os desenvolvedores muitas vezes precisavam usar outros métodos que retornavam cópias de matrizes, o que prejudicava 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 no Codepen de como .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, é possível encadear várias chamadas de .with() ou até mesmo outros métodos de matriz. O exemplo a seguir demonstra
o incremento da segunda e da terceira idades 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 novos métodos imutáveis
Três outros métodos se tornaram interoperáveis recentemente:
Array.prototype.toReversed()que inverte a matriz sem alterar a matriz original.Array.prototype.toSorted()que classifica a matriz sem mudar a matriz original.Array.prototype.toSpliced()que funciona como.splice(), mas sem alterar a matriz original.
De acordo com a MDN, esses três métodos são a versão de cópia das contrapartes. Esses métodos também podem ser usados quando a imutabilidade é esperada ou preferida.
Em resumo, as atualizações imutáveis podem ser feitas com mais facilidade em JavaScript usando um dos quatro métodos apresentados neste artigo. Especificamente, o método .with() facilita a atualização de um único elemento da matriz sem alterar a matriz original.