Clonagem de objetos em JavaScript: como não quebrar o código

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que a simples atribuição é uma armadilha?

\n

Imagine que você está escrevendo um aplicativo de anotações. O usuário cria um cartão com título e texto, depois quer fazer uma cópia para alterá-lo um pouco. Você escreve:

\n
const original = { title: 'Meu plano', text: 'Comprar leite' };\nconst copy = original;\ncopy.title = 'Novo plano';\nconsole.log(original.title); // 'Novo plano' — ops!
\n

Situação familiar? Se sim, você encontrou a principal característica dos objetos em JavaScript: eles são passados por referência. A atribuição copy = original não cria um novo objeto, apenas copia a referência para o mesmo espaço de memória. Qualquer alteração em copy reflete em original.

\n

No Stack Overflow, a pergunta "How do I correctly clone a JavaScript object?" acumulou milhares de visualizações e dezenas de respostas. Este é um dos problemas mais comuns para iniciantes e até desenvolvedores experientes. Neste artigo, vamos abordar todas as formas de clonagem de objetos em JavaScript, desde as simples até as avançadas, e descobrir qual abordagem é melhor em cada situação.

\n\n

Cópia superficial (Shallow copy): rápida e simples

\n

A cópia superficial cria um novo objeto, mas para objetos aninhados (arrays, outros objetos) copia apenas as referências. É ideal para estruturas planas, mas perigosa para estruturas profundas.

\n\n

Método 1: Operador spread (…)

\n

A forma mais moderna e legível:

\n
const original = { name: 'Ana', age: 25 };\nconst clone = { ...original };\nclone.age = 30;\nconsole.log(original.age); // 25 — tudo certo!
\n

Prós: notação curta, funciona com arrays e objetos. Contras: não copia métodos (funções) e propriedades do tipo símbolo.

\n\n

Método 2: Object.assign()

\n

Método clássico para copiar objeto sem referências no nível superior:

\n
const source = { a: 1, b: { c: 2 } };\nconst target = Object.assign({}, source);\ntarget.a = 100; // source.a não muda\ntarget.b.c = 999; // source.b.c também muda — shallow!
\n

Este método é especialmente útil quando você precisa combinar vários objetos: Object.assign({}, obj1, obj2).

\n\n

Método 3: Loop for…in

\n

Uma forma antiga, mas ainda funcional. Útil para entender a mecânica:

\n
function shallowClone(obj) {\n  const clone = {};\n  for (let key in obj) {\n    if (obj.hasOwnProperty(key)) {\n      clone[key] = obj[key];\n    }\n  }\n  return clone;\n}
\n

Hoje é raramente usado, mas demonstra bem como funciona a clonagem manual de objetos.

\n\n

Cópia profunda (Deep copy): quando você precisa de tudo

\n

Se o seu objeto contém objetos aninhados, arrays ou datas, a shallow copy vai te decepcionar. Você precisa de clonagem profunda js.

\n\n

Método 4: JSON.parse + JSON.stringify

\n

O "gambiarra" mais popular:

\n
const original = { \n  name: 'Pedro', \n  address: { city: 'Moscou', street: 'Tverskaya' },\n  date: new Date()\n};\nconst clone = JSON.parse(JSON.stringify(original));\nclone.address.city = 'SP';\nconsole.log(original.address.city); // 'Moscou' — ufa!
\n

Mas há ressalvas: este método perde funções, undefined, Symbol, e Date se transforma em string. Para dados simples — ok, para complexos — não.

\n\n

Método 5: structuredClone() — o novo padrão

\n

Desde 2022, o JavaScript possui o método nativo structuredClone:

\n
const original = { \n  scores: [10, 20, 30], \n  meta: { level: 'easy' },\n  date: new Date()\n};\nconst clone = structuredClone(original);\nclone.meta.level = 'hard';\nconsole.log(original.meta.level); // 'easy'
\n

Prós: suporta Date, Map, Set, ArrayBuffer, referências recursivas. Contras: não suporta funções, elementos DOM, Error. Funciona

Blogs

Book Recommendations