Clonar objetos es una tarea habitual de programación para almacenar o pasar datos. Hasta hace poco, los desarrolladores tenían que recurrir a bibliotecas de terceros para realizar esta operación debido a necesidades avanzadas como la copia profunda o el mantenimiento de referencias circulares.

Afortunadamente, eso ya no es necesario, gracias al nuevo método incorporado llamado structuredClone(). Esta función proporciona una forma fácil y eficiente de clonar objetos en profundidad sin bibliotecas externas. Funciona en la mayoría de los navegadores modernos (a partir de 2022) y en Node.js (a partir de v17).

En este artículo, aprenderemos a utilizar la función structuredClone() para clonar objetos, junto con las ventajas y desventajas de hacerlo.

¿Cómo utilizar structuredClone()?


structuredClone() funciona de forma muy intuitiva; pase el objeto original a la función, y ésta devolverá una copia en profundidad con una referencia y referencias de propiedades del objeto diferentes.

JavaScript

const obj = { name: 'Mike', friends: [{ name: 'Sam' }] };
const clonedObj = structuredClone(obj);

console.log(obj.name === clonedObj); // false
console.log(obj.friends === clonedObj.friends); // false

A diferencia del conocido hack JSON stringify/parse, structuredClone() permite clonar referencias circulares.

JavaScript

const car = {
  make: 'Toyota',
};

car.basedOn = car;

const cloned = structuredClone(car);

console.log(car.basedOn === cloned.basedOn); // false

// 👇 Circular reference is cloned
console.log(car === car.basedOn); // true

Ventajas de structuredClone()


¿Qué hace que structuredClone() sea tan bueno? Bueno, lo hemos dicho desde la introducción; te permite hacer copias profundas de objetos sin dificultad. No necesitas instalar ninguna librería de terceros o usar JSON.stringify/parse para hacerlo.

Con structuredClone(), puedes clonar objetos que tienen referencias circulares, que es algo que no es posible con el enfoque JSON. Puedes clonar objetos complejos y estructuras de datos con facilidad.

structuredClone() puede realizar copias profundas de tantos niveles como necesite; crea una copia completamente nueva del objeto original sin referencias ni propiedades compartidas. Esto significa que cualquier cambio realizado en el objeto clonado no afectará al original, y viceversa.

Limitaciones de structuredClone()


Aunque structuredClone() es una potente función para clonar objetos y estructuras de datos, tiene algunas limitaciones que merece la pena señalar.

No puede clonar funciones ni métodos


Sí, structuredClone() no puede clonar funciones o métodos. Esto se debe al algoritmo de clonación estructurada que utiliza la función. El algoritmo no puede duplicar objetos de función y lanza una excepción DataCloneError.

function func() {}

// Error: func could not be cloned
const funcClone = structuredClone(func);
const car = {
  make: 'BMW',
  move() {
    console.log('vroom vroom..');
  },
};

car.basedOn = car;
// ❌ Error: move() could not be cloned
const cloned = structuredClone(car);

Como puede ver en el ejemplo anterior, intentar utilizar structuredClone() en una función o un objeto con un método provocará un error.

No puede clonar elementos DOM


De forma similar, el algoritmo de clonado estructurado utilizado por structuredClone() no puede clonar elementos DOM. Pasar un objeto HTMLElement a structuredClone() causará un error como el anterior.

const input = document.querySelector('#text-field');

// ❌ Failed: HTMLInputElement object could not be cloned.
const clone = structuredClone(input);

No preserva la propiedad lastIndex de RegExp
Cuando se clona un objeto RegExp con structuredClone() la propiedad lastIndex de un RegExp no se conserva en el clon:

const regex = /beauty/g;
const str = 'Coding Beauty: JS problems are solved at Coding Beauty';

console.log(regex.index);
console.log(regex.lastIndex); // 7

const regexClone = structuredClone(regex);
console.log(regexClone.lastIndex); // 0

Otras limitaciones de structuredClone()


No conserva los metadatos o descriptores de propiedades. Por ejemplo, si un descriptor de propiedad marca un objeto como de sólo lectura, el clon del objeto será de lectura/escritura por defecto.


No conserva las propiedades no enumerables en el clon.


Estas limitaciones no deberían ser un gran inconveniente para la mayoría de los casos de uso, pero aún así, es importante conocerlas para evitar comportamientos inesperados al utilizar la función.

Transferir valor con structuredClone()


Cuando clona un objeto, puede transferir objetos concretos en lugar de hacer copias utilizando la propiedad transfer en el segundo parámetro de opciones que tiene structuredClone().

Esto significa que puede mover objetos entre el objeto original y el clonado sin crear duplicados. El objeto original no puede ser utilizado después de la transferencia.

Digamos que tienes algunos datos en un buffer que necesitas validar antes de guardar. Clonando el buffer y validando los datos clonados en su lugar, puedes evitar cualquier cambio no deseado en el buffer original.

Además, si transfieres los datos validados al búfer original, se convertirán en inmutables y se bloqueará cualquier intento accidental de modificarlos. Esto puede darte más tranquilidad cuando trabajes con datos importantes.

Veamos un ejemplo:

const uInt8Array = Uint8Array.from({ length: 1024 * 1024 * 16 }, (v, i) => i);

const transferred = structuredClone(uInt8Array, {
  transfer: [uInt8Array.buffer],
});

console.log(uInt8Array.byteLength); // 0

En este ejemplo, creamos un buffer UInt8Array y lo llenamos con datos. Luego, lo clonamos usando structuredClone() y transferimos el buffer original al objeto clonado. Esto hace que el array original sea inutilizable, asegurando que no será modificado accidentalmente.

Puntos claves


structuredClone() es una útil función incorporada en JavaScript para crear copias profundas de objetos sin librerías externas. Tiene algunas limitaciones, como no poder clonar funciones, métodos o elementos DOM y no preservar algún tipo de propiedades en el clon.

Puedes utilizar la opción de transferencia para mover objetos entre el objeto original y el clonado sin crear duplicados, lo que puede ser útil para validar datos o asegurar la inmutabilidad. En general, structuredClone() es una valiosa adición al conjunto de herramientas de un desarrollador y hace que la clonación de objetos en JavaScript sea más fácil que nunca.

Todas las locuras de JavaScript


Una cautivadora guía sobre las sutiles advertencias y las partes menos conocidas de JavaScript.

Fuente

Plataforma de cursos gratis sobre programación