Cómo clonar objetos con estructuras anidadas en JavaScript, comparando técnicas tradicionales con structuredClone().
En JavaScript, copiar objetos que contienen estructuras anidadas siempre ha sido un tema peliagudo. Las soluciones habituales, como usar el operador spread o la combinación de JSON.stringify()
y JSON.parse()
, tienen limitaciones que pueden generar errores según qué objetos internos contengan. Desde Marzo de 2022 ya se puede usar la función structuredClone()
en todos los navegadores habituales, un método que busca solventar estos problemas en muchos casos.
Aunque usar el operador spread ({...obj}
) resulta práctico para copiar propiedades a nivel superficial, su copia es shallow; es decir, si el objeto contiene subobjetos, éstos se mantienen referenciados. Por ejemplo:
const original = { a: 1, b: { c: 2 } };const copia = { ...original };
copia.b.c = 3;console.log(original.b.c); // Imprime 3 en vez de 2, pues el objeto anidado sigue siendo el mismo
Otra estrategia popular es combinar JSON.stringify()
y JSON.parse()
. Esta técnica permite copiar objetos de forma profunda, pero presenta inconvenientes:
TypeError: Converting circular structure to JSON
.undefined
y las funciones se omiten.const objeto = { a: 1, b: { c: 2 }, d: undefined, e: () => console.log('Hola')};
objeto.f = objeto
try { const clon = JSON.parse(JSON.stringify(objeto)); console.log(clon);} catch (error) { console.error('Error al clonar el objeto:', error);}
Con la llegada de structuredClone()
, se introduce un método que realiza una clonación profunda utilizando el algoritmo de clonación estructurada propio de la plataforma. Este método permite copiar objetos con datos cíclicos sin provocar errores y conserva valores que JSON.parse+stringify descarta, como undefined
. Sin embargo, no clona funciones; si el objeto contiene alguna, se lanzará un error.
const objetoValido = { a: 1, b: { c: 2 }, d: undefined };objetoValido.e = objetoValido;const clon = structuredClone(objetoValido);console.log(clon);// Salida: { a: 1, b: { c: 2 }, d: undefined }
const objetoConFuncion = { a: 1, b: () => console.log('Esto no se puede clonar')};
try { const clonErroneo = structuredClone(objetoConFuncion);} catch (error) { console.error('No se pueden clonar funciones:', error);}
En conclusión, structuredClone()
ofrece una alternativa a tener en cuenta para copiar objetos complejos en JavaScript, especialmente cuando se trata de estructuras anidadas y datos cíclicos. Si bien supera algunas de las limitaciones del operador spread y de la técnica con JSON Parse y Stringify, es importante tener en cuenta sus restricciones, principalmente en lo que respecta a funciones. La elección del método dependerá del tipo de objeto a clonar y de los requisitos específicos del momento.