|

Três maneiras de clonar objetos com JavaScript

Três maneiras de clonar objetos com JavaScript Foto por Tanner Yould em Unsplash

Três Formas de Clonar Objetos com JavaScript

Objetos em JavaScript são valores com referências, você não pode simplesmente copiar um objeto usando o operador de igualdade =. Mas não se preocupe! Aqui eu listo três maneiras que você pode usar para clonar um objeto 💁

const drinks = { soda: '🥤', tea: '🍵' }

// Usando a sintaxe "Spread"
{ ...drinks }

// Usando o método "Object.assign"
Object.assign({}, drinks)

// Usando métodos "JSON"
JSON.parse(JSON.stringify(drinks))

// RESULTADO:
// { soda: '🥤', tea: '🍵' }

Objetos são Tipos de Referência

Talvez a primeira pergunta que você tenha seja: por que eu não posso usar o =? Vamos ver o que acontece se você fizer isso:

const obj = { abc: '123', def: '456' };

const obj2 = obj;

console.log(
  obj, // { abc: '123', def: '456' };
  obj2, // { abc: '123', def: '456' };
);

Até aqui ambos os objetos parecem mostrar a mesma coisa. Não tivemos nenhum problema, certo? Mas vamos ver o que acontece se editarmos o nosso segundo objeto:

const obj2.ghi = '789';

console.log(obj2);
// { abc: '123', def: '456', ghi: '789' }; <-- ✅

console.log(obj);
// { abc: '123', def: '456', ghi: '789' }; <-- 🤦

O QUÊ?! Eu mudei o obj2 mas o obj também foi afetado. Isto acontece porque Objetos são tipos de referência. Quando você usa o =, ele copia a referência para o espaço da memória que ele ocupa. Tipos de referência não armazenam valores, eles apontam para um valor na memória.

Se você quiser aprender mais sobre isso, eu recomendo que você leia o artigo do MDN Trabalhando Com Objetos

1. Usar a sintaxe Spread (…)

Seu objeto sera clonado ao usar a sintaxe spread. Porém observe que esta será uma cópia superficial.

const drinks = { soda: '🥤', tea: '🍵' }

const cloneDrinks = { ...drinks };

console.log(cloneDrinks);
// { soda: '🥤', tea: '🍵' }

2. Usar o método Object.assign

O método Object.assign também cria uma cópia superficial do objeto.

const drinks = { soda: '🥤', tea: '🍵' }

const cloneDrinks = Object.assign({}, drinks);

console.log(cloneDrinks);
// { soda: '🥤', tea: '🍵' }

Observe o objeto vazio {} como primeiro argumento, isto irá garantir o objeto original não sofra mutações 🧬

3. Usar métodos JSON

Esta última maneira irá gerar uma cópia profunda. Essa é uma maneira rápida e ‘suja’ de clonar um objeto profundamente. Você pode usar bibliotecas como lodash ou underscore para soluções mais robustas.

const drinks = { soda: '🥤', tea: '🍵' }

const cloneDrinks = JSON.parse(JSON.stringify(drinks));

console.log(cloneDrinks);
// { soda: '🥤', tea: '🍵' }

Apesar de ser uma solução plausível, a utilização dos métodos de objetos JSON podem trazer problemas. Se você tiver funções ou objetos do tipo Símbolo dentro do objeto a ser clonado, estes não funcionarão como esperado.

Cópia Superficial x Cópia Profunda

Ao usar spread ... para copiar um objeto, apenas uma cópia superficial está sendo realizada. Se existirem objetos multidimensionais ou aninhados dentro do objeto original, a cópia não funcionará como esperado. Veja o seguinte exemplo:

const originalMonument = {
  symbol: '🗽',
  location: {
    city: 'New York',
    country: 'United States',
  },
};

Cópia Superficial

Vamos clonar o nosso objeto usando spread:

const shallowClone = { ...originalMonument };

// Mudaremos o nosso objeto clonado
shallowClone.symbol = '🕌';
shallowClone.location.city = 'Agra';
shallowClone.location.country = 'India';

Então mudamos o nosso objeto clonado mudando a propriedade cidade. Vamos ver o que acontece:

console.log(shallowClone);
// { symbol: '🕌', location: { city: 'Agra', country: 'India'} }

console.log(originalMonument);
// { symbol: '🕌', location: { city: 'Agra', country: 'India'} } <-- 😨

Uma cópia superficial significa que apenas o primeiro nível é copiado. Níveis mais profundos, como objetos aninhados, são apenas referenciados.

Cópia Profunda

Vamos utilizar o mesmo exemplo, mas desta vez com uma cópia profunda através de JSON

const deepClone = JSON.parse(JSON.stringify(originalMonument));

// Novamente mudaremos o nosso objeto clonado
shallowClone.symbol = '🕌';
shallowClone.location.city = 'Agra';
shallowClone.location.country = 'India';

console.log(deepClone);
// { symbol: '🕌', location: { city: 'Agra', country: 'India'} }

console.log(originalMonument);
// { symbol: '🗽', location: { city: 'New York', country: 'United States'} } <-- 👌

Como você pode ver, utilizar os métodos de JSON criam uma cópia real do objeto até mesmo com objetos aninhados. Na maioria das vezes uma cópia superficial é o suficiente, você não precisa de uma cópia profunda todo tempo. Você precisa analisar o que cada caso necessita, e assim utilizar a melhor ferramenta possível para a sua situação. Espero que este artigo tenha o ajudado a clonar objetos usando JavaScript.