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:
-
Iterar elementos de una matriz sin bucles
Los ejemplos son muy abstractos debido a que hay ciclos. Nuestra condición será la siguiente: es necesario seleccionar todos los elementos del array mediante un atributo ...
-
Cómo detectar la dirección de desplazamiento en una página usando JavaScript
A veces es necesario detectar la dirección del desplazamiento vertical en un sitio, por ejemplo, para realizar algunas acciones con el footer o el header. Escribamos un c...
-
Temporizador de cuenta regresiva en JavaScript
A menudo, en los sitios que venden algo, se puede encontrar un temporizador de cuenta regresiva hasta una fecha determinada. Este tipo de script suele ser necesario para ...
Leave a Reply