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:
-
Cómo realizar solicitudes asincrónicas en un bucle en JavaScript
Implementar solicitudes asincrónicas dentro de un bucle de JavaScript puede no parecer obvio al principio. Al realizar solicitudes asincrónicas dentro de un bucle de Java...
-
Cómo encontrar la distancia entre dos puntos en un mapa usando JavaScript (TypeScript)
Si se tienen las coordenadas de dos puntos en un mapa, calcular la distancia entre ellos es bastante sencillo. Este tipo de cálculo se utiliza habitualmente en aplicacion...
-
Cómo enviar un formulario usando jQuery Ajax ($.ajax)
Enviar un formulario mediante el método $.ajax de jQuery es una forma eficaz de enviar datos al servidor sin recargar la página. Este enfoque mejora la experiencia del us...
Leave a Reply