Cómo clonar (copiar) objetos y arrays en JavaScript
Clonación de un array
1. Uso del operador spread (...):
const originalArray = [1, 2, 3]; const clonedArray = [...originalArray]; console.log(clonedArray); // Output: [1, 2, 3]
2. Uso de Array.prototype.slice():
const originalArray = [1, 2, 3]; const clonedArray = originalArray.slice(); console.log(clonedArray); // Output: [1, 2, 3]
3. Uso de Array.from():
const originalArray = [1, 2, 3]; const clonedArray = Array.from(originalArray); console.log(clonedArray); // Output: [1, 2, 3]
4. Uso de structuredClone() (clonación profunda):
const originalArray = [1, { key: "value" }];
const clonedArray = structuredClone(originalArray);
console.log(clonedArray); // Output: [1, { key: "value" }]
Clonación de un objeto
1. Uso del operador spread (...):
const originalObject = { a: 1, b: 2 };
const clonedObject = { ...originalObject };
console.log(clonedObject); // Output: { a: 1, b: 2 }
2. Using Object.assign():
const originalObject = { a: 1, b: 2 };
const clonedObject = Object.assign({}, originalObject);
console.log(clonedObject); // Output: { a: 1, b: 2 }
3. Uso de structuredClone() (clonación profunda):
const originalObject = { a: 1, b: { c: 2 } };
const clonedObject = structuredClone(originalObject);
console.log(clonedObject); // Output: { a: 1, b: { c: 2 } }
4. Uso de JSON.parse() y JSON.stringify() (clonación profunda):
const originalObject = { a: 1, b: { c: 2 } };
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject); // Output: { a: 1, b: { c: 2 } }
Este método no admite funciones, undefined, Symbol o referencias circulares.
Clonación profunda vs. clonación superficial
- Clonación superficial (p. ej., utilizando
...,slice()oObject.assign()):
Solo clona el primer nivel del objeto u array. Los objetos u arrays anidados siguen siendo referencias al original. - Clonación profunda (p. ej.,
structuredClone()oJSON.parse(JSON.stringify())):
Clona toda la estructura, incluidos los arrays u objetos anidados.
Cuándo utilizar cada método
- Utilice la clonación superficial para estructuras simples y planas.
- Utilice la clonación profunda si el objeto u array contienen estructuras anidadas y necesita evitar referencias a los datos originales.
Clonación de un array o de un objeto que contiene métodos (funciones)
Clonación superficial
Uso del operador de propagación (...) u Object.assign()
- Las funciones en el objeto u array se tratan como cualquier otra propiedad.
- La referencia a la función se copia al objeto o matriz clonados.
- Las versiones original y clonada compartirán la misma función en la memoria.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = { ...originalObject };
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Para arrays: si la matriz contiene funciones, se copian las referencias a esas funciones. Uso del operador de propagación (...) o slice()
const originalArray = [1, 2, function () { return 42; }];
const clonedArray = [...originalArray];
console.log(clonedArray[2]()); // Output: 42
console.log(clonedArray[2] === originalArray[2]); // Output: true (same reference)
Clonación profunda
Uso de JSON.parse(JSON.stringify())
- Los métodos (funciones) se perderán porque JSON solo admite tipos de datos serializables (por ejemplo, números, cadenas, matrices y objetos).
- Cualquier propiedad que contenga funciones no existirá en el objeto o array clonado.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject.method); // Output: undefined
Uso de structuredClone() (clonación profunda)
Las funciones no se clonan. La clonación estructurada no admite funciones y las eliminará del objeto o array clonado.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = structuredClone(originalObject);
console.log(clonedObject.method); // Output: undefined
Puntos clave para recordar
1. Clonación superficial:
- Las funciones se copian por referencia, lo que significa que los objetos/arrays clonados y originales compartirán la misma función.
2. Clonación profunda:
- Las funciones generalmente se pierden (eliminan) cuando se usan métodos como
JSON.parse(JSON.stringify())ostructuredClone()porque no son serializables.
3. Si necesita clonar un objeto o array con métodos, es posible que deba escribir una función de clonación personalizada para manejar las funciones explícitamente o usar bibliotecas de terceros.
Clonación personalizada para objetos con métodos
Puede manejar funciones manualmente en su lógica de clonación:
function customClone(obj) {
const clone = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (typeof obj[key] === 'function') {
clone[key] = obj[key]; // Copy functions by reference
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
clone[key] = customClone(obj[key]); // Recursively clone objects
} else {
clone[key] = obj[key]; // Copy primitives
}
}
return clone;
}
const original = {
value: 42,
method() {
return this.value;
}
};
const cloned = customClone(original);
console.log(cloned.method()); // Output: 42
console.log(cloned.method === original.method); // Output: true (same reference)
Este enfoque garantiza que se conserven las funciones mientras se clonan profundamente otras propiedades.
Uso de bibliotecas de terceros
En los proyectos, suelo utilizar Lodash o jQuery. Ambas bibliotecas tienen métodos de clonación profunda. Cuando se utiliza Lodash o jQuery para realizar una clonación profunda, ambas bibliotecas tratan las funciones de forma diferente a los métodos nativos como JSON.parse(JSON.stringify()) o structuredClone().
Clonación profunda con Lodash
Uso de _.cloneDeep() de Lodash:
- Lodash realiza una clonación profunda del objeto o array, incluidas las estructuras anidadas.
- Las funciones (métodos) en el objeto o array se copian por referencia. Esto significa que la función en el objeto clonado o array apuntará a la misma referencia de memoria que el original.
const _ = require('lodash');
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = _.cloneDeep(originalObject);
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Lodash no elimina funciones, a diferencia de JSON.parse(JSON.stringify()), pero no crea una nueva copia de la función. Conserva una referencia a la original.
Clonación profunda con jQuery
Uso de $.extend() de jQuery:
- Se utiliza
$.extend()de jQuery para clonar objetos. Para lograr una clonación profunda, se pasa true como primer argumento. - Al igual que Lodash, jQuery copia funciones por referencia.
const originalObject = {
value: 42,
method: function () {
return this.value;
}
};
const clonedObject = $.extend(true, {}, originalObject);
console.log(clonedObject.method()); // Output: 42
console.log(clonedObject.method === originalObject.method); // Output: true (same reference)
Limitaciones de $.extend():
- El mecanismo de clonación de jQuery es más simple y menos robusto en comparación con Lodash.
- No maneja algunos casos de uso avanzados (por ejemplo, referencias circulares) con tanta eficiencia como Lodash.
Publicaciones similares:
-
Temporizador de cuenta regresiva en JavaScript
Los temporizadores de cuenta regresiva se utilizan comúnmente en sitios web que promocionan productos, servicios u ofertas especiales. Es frecuente verlos en páginas de d...
-
Reloj simple de JavaScript
Existen numerosos ejemplos de cómo implementar un reloj con JavaScript, y aunque los enfoques pueden variar ligeramente, la mayoría sigue una idea similar. Normalmente, e...
-
Desplazamiento suave hacia el ancla mediante JavaScript
El desplazamiento suave es una característica popular del diseño web que mejora la experiencia del usuario al permitir una navegación fluida entre las secciones de una pá...
Leave a Reply