Clonación de objetos en JavaScript: cómo no romper el código

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿por qué la simple asignación es una trampa?

\n

Imagina que estás escribiendo una aplicación de notas. El usuario crea una tarjeta con un título y un texto, luego quiere hacer una copia para modificarla un poco. Escribes:

\n
const original = { title: 'Mi plan', text: 'Comprar leche' };\nconst copy = original;\ncopy.title = 'Nuevo plan';\nconsole.log(original.title); // 'Nuevo plan' — ¡uy!
\n

¿Te resulta familiar? Si es así, te has topado con la característica principal de los objetos en JavaScript: se pasan por referencia. La asignación copy = original no crea un nuevo objeto, solo copia la referencia a la misma ubicación de memoria. Cualquier cambio en copy se refleja en original.

\n

En Stack Overflow, la pregunta "How do I correctly clone a JavaScript object?" ha acumulado miles de visitas y decenas de respuestas. Es uno de los problemas más comunes tanto para principiantes como para desarrolladores experimentados. En este artículo, analizaremos todas las formas de clonación de objetos en JavaScript, desde las simples hasta las avanzadas, y descubriremos qué enfoque es mejor en cada situación.

\n\n

Copia superficial (Shallow copy): rápida y sencilla

\n

La copia superficial crea un nuevo objeto, pero para objetos anidados (arrays, otros objetos) solo copia las referencias. Es ideal para estructuras planas, pero peligrosa para las profundas.

\n\n

Método 1: Operador spread (…)

\n

La forma más moderna y legible:

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

Ventajas: escritura corta, funciona con arrays y objetos. Desventajas: no copia métodos (funciones) ni propiedades de tipo Symbol.

\n\n

Método 2: Object.assign()

\n

Método clásico para copiar un objeto sin referencias en el nivel superior:

\n
const source = { a: 1, b: { c: 2 } };\nconst target = Object.assign({}, source);\ntarget.a = 100; // source.a no cambiará\ntarget.b.c = 999; // source.b.c también cambiará — ¡shallow!
\n

Este método es especialmente útil cuando necesitas combinar varios objetos: Object.assign({}, obj1, obj2).

\n\n

Método 3: Bucle for…in

\n

Una forma antigua pero aún funcional. Útil para entender la 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

Hoy en día se usa raramente, pero demuestra perfectamente cómo funciona la clonación manual de objetos.

\n\n

Copia profunda (Deep copy): cuando lo necesitas todo

\n

Si tu objeto contiene objetos anidados, arrays o fechas, la shallow copy te fallará. Necesitas una clonación profunda js.

\n\n

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

\n

El "parche" más popular:

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

Pero tiene matices: este método pierde funciones, undefined, Symbol, y Date se convierte en una cadena. Para datos simples está bien, para datos complejos no.

\n\n

Método 5: structuredClone() — el nuevo estándar

\n

Desde 2022, JavaScript tiene un método incorporado llamado 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

Ventajas: soporta Date, Map, Set, ArrayBuffer, referencias recursivas. Desventajas: no soporta funciones, elementos DOM, Error. Funciona

Blogs

Book Recommendations