Introdução
Ao trabalhar com JavaScript, muitas vezes precisamos copiar objetos e arrays. No entanto, há uma diferença crucial entre shallow copy (cópia rasa) e deep copy (cópia profunda), e entender essa distinção pode evitar bugs e comportamentos inesperados no código.
Já aconteceu de você modificar um objeto copiado e, de repente, perceber que o original também foi alterado? Isso tem tudo a ver com o tipo de cópia utilizada. Vamos explorar essa diferença de forma simples e prática!
Índice
Sr# | Tópicos |
---|---|
1 | O que é uma cópia de objeto? |
2 | O que é Shallow Copy? |
3 | Como fazer uma Shallow Copy? |
4 | Problemas da Shallow Copy |
5 | O que é Deep Copy? |
6 | Como fazer uma Deep Copy? |
7 | Métodos nativos do JavaScript para Deep Copy |
8 | Quando usar Shallow Copy e Deep Copy? |
9 | Exemplos práticos |
10 | Conclusão |
11 | Perguntas Frequentes |
1. O que é uma cópia de objeto?
Em JavaScript, objetos e arrays são copiados por referência, ou seja, ao atribuir um objeto a uma nova variável, na verdade, estamos apenas criando um novo ponteiro para o mesmo espaço de memória. Isso significa que alterações feitas no novo objeto também afetam o original.
2. O que é Shallow Copy?
Uma shallow copy (cópia rasa) cria um novo objeto copiando apenas os valores do primeiro nível. Se o objeto contém outros objetos ou arrays aninhados, esses continuam sendo referenciados e não copiados.
3. Como fazer uma Shallow Copy?
Existem várias maneiras de criar uma shallow copy em JavaScript:
// Usando spread operator
const obj1 = { nome: "João", idade: 30 };
const obj2 = { ...obj1 };
// Usando Object.assign()
const obj3 = Object.assign({}, obj1);
Esses métodos criam uma cópia superficial do objeto.
4. Problemas da Shallow Copy
Se houver propriedades que sejam objetos ou arrays dentro do objeto copiado, qualquer modificação nessas propriedades será refletida no original:
const obj1 = { nome: "João", endereco: { cidade: "São Paulo" } };
const obj2 = { ...obj1 };
obj2.endereco.cidade = "Rio de Janeiro";
console.log(obj1.endereco.cidade); // "Rio de Janeiro"
Isso acontece porque o objeto interno ainda está sendo referenciado na memória.
5. O que é Deep Copy?
Uma deep copy (cópia profunda) copia completamente um objeto, incluindo todos os seus objetos aninhados, garantindo que o novo objeto seja independente do original.
6. Como fazer uma Deep Copy?
A maneira mais simples (mas não sempre ideal) de criar uma deep copy é utilizando JSON.stringify()
e JSON.parse()
:
const obj1 = { nome: "João", endereco: { cidade: "São Paulo" } };
const obj2 = JSON.parse(JSON.stringify(obj1));
obj2.endereco.cidade = "Rio de Janeiro";
console.log(obj1.endereco.cidade); // "São Paulo"
Esse método funciona, mas não suporta funções ou valores como undefined e Date.
7. Métodos nativos do JavaScript para Deep Copy
Desde o ECMAScript 2021, podemos usar structuredClone()
:
const obj1 = { nome: "João", endereco: { cidade: "São Paulo" } };
const obj2 = structuredClone(obj1);
Isso resolve as limitações do JSON.stringify()
, preservando valores como Date
e undefined
.
8. Quando usar Shallow Copy e Deep Copy?
- Shallow Copy: Quando os dados são simples e não contêm objetos aninhados.
- Deep Copy: Quando precisamos garantir que o objeto copiado seja totalmente independente do original.
9. Exemplos práticos
Vamos ver um exemplo onde a escolha errada pode causar problemas:
const carrinhoOriginal = { produto: "Camisa", detalhes: { tamanho: "M", cor: "azul" } };
const carrinhoCopiado = { ...carrinhoOriginal };
carrinhoCopiado.detalhes.tamanho = "G";
console.log(carrinhoOriginal.detalhes.tamanho); // "G" - Isso pode ser um problema!
Agora, com deep copy:
const carrinhoSeguro = structuredClone(carrinhoOriginal);
carrinhoSeguro.detalhes.tamanho = "G";
console.log(carrinhoOriginal.detalhes.tamanho); // "M" - Correto!
10. Conclusão
Entender a diferença entre shallow e deep copy no JavaScript é essencial para evitar erros ao manipular objetos e arrays. Se o objeto for simples, uma cópia rasa pode ser suficiente. Porém, se houver objetos aninhados, é melhor optar por uma deep copy para evitar efeitos colaterais indesejados.
11. Perguntas Frequentes
1. Qual a maneira mais rápida de criar uma cópia de um objeto?
Se não houver objetos aninhados, usar o spread operator (...
) ou Object.assign()
é a opção mais rápida.
2. O que acontece se eu modificar um objeto copiado superficialmente?
Se houver objetos aninhados, as mudanças afetarão também o original, pois a referência interna ainda é compartilhada.
3. Quando devo usar JSON.stringify() e JSON.parse()?
Se o objeto for simples e não contiver funções, classes ou valores como undefined
, essa pode ser uma boa solução.
4. structuredClone() funciona em todos os navegadores?
A partir do ECMAScript 2021, sim. Para compatibilidade com navegadores mais antigos, bibliotecas como lodash.cloneDeep()
podem ser usadas.
5. Existe uma biblioteca que facilita Deep Copy?
Sim, a biblioteca Lodash tem a função _.cloneDeep()
que resolve esse problema com eficiência.
Agora que você entende a diferença entre shallow e deep copy, pode evitar erros e escrever códigos mais seguros e eficientes em JavaScript!