Extraer y Modificar Partes de Arreglos: slice() y splice()
Formas de Copiar Arreglos en JavaScript
🤔 ¿Por Qué Copiar un Arreglo?
A veces, queremos trabajar con los datos de un arreglo sin modificar el original. Si simplemente asignamos un arreglo a otra variable, no estamos creando una copia, sino que ambas variables apuntarán al mismo arreglo en la memoria.
let original = [1, 2, 3];let referencia = original; // NO es una copia
referencia.push(4);
console.log(original); // Muestra [1, 2, 3, 4] ¡El original fue modificado!console.log(referencia); // Muestra [1, 2, 3, 4]Para evitar esto, necesitamos crear una copia independiente.
📋 Copias Superficiales (Shallow Copies)
La mayoría de los métodos integrados crean copias superficiales. Esto significa que copian los elementos del primer nivel del arreglo. Si esos elementos son valores primitivos (números, strings, booleanos), se copian por valor y son independientes. Pero si los elementos son objetos o arreglos, se copia la referencia a esos objetos/arreglos, no los objetos/arreglos en sí.
1. Usando slice()
Como vimos, llamar a slice() sin argumentos crea una copia superficial de todo el arreglo.
let numeros = [10, 20, 30];let copiaNumeros = numeros.slice();
copiaNumeros.push(40);
console.log(numeros); // Muestra [10, 20, 30] (Original intacto)console.log(copiaNumeros); // Muestra [10, 20, 30, 40]2. Usando el Operador Spread (...)
El operador Spread es una forma moderna y muy legible de crear copias superficiales.
let colores = ["Rojo", "Verde", "Azul"];let copiaColores = [...colores];
copiaColores[0] = "Morado";
console.log(colores); // Muestra ["Rojo", "Verde", "Azul"]console.log(copiaColores); // Muestra ["Morado", "Verde", "Azul"]3. Usando Array.from()
Array.from() crea una nueva instancia de Array a partir de un objeto iterable (como otro arreglo).
let herramientas = ["Martillo", "Sierra"];let copiaHerramientas = Array.from(herramientas);
copiaHerramientas.pop(); // Quita "Sierra"
console.log(herramientas); // Muestra ["Martillo", "Sierra"]console.log(copiaHerramientas); // Muestra ["Martillo"]El Problema de las Copias Superficiales con Objetos/Arreglos Anidados
Si el arreglo contiene objetos o más arreglos, la copia superficial solo copia las referencias:
let originalAnidado = [{ id: 1 }, { id: 2 }];let copiaSuperficial = [...originalAnidado];
// Modificamos un objeto DENTRO de la copiacopiaSuperficial[0].id = 99;
// ¡El cambio se refleja en el original también!console.log(originalAnidado[0].id); // Muestra 99console.log(copiaSuperficial[0].id); // Muestra 99⚠️ ¡Cuidado! Con arreglos anidados u objetos dentro de arreglos, slice(),
... y Array.from() no crean copias independientes de esos elementos
internos.
🧱 Copias Profundas (Deep Copies)
Para crear una copia completamente independiente, incluyendo objetos y arreglos anidados, necesitamos una copia profunda. No hay un método integrado simple y universal para esto, pero hay técnicas comunes:
1. Usando JSON.stringify() y JSON.parse()
Una forma común (con limitaciones) es convertir el arreglo a un string JSON y luego de vuelta a un objeto/arreglo JavaScript.
let originalProfundo = [{ valor: 10 }, [{ sub: 20 }]];let copiaProfunda = JSON.parse(JSON.stringify(originalProfundo));
// Modificamos un objeto anidado en la copiacopiaProfunda[1][0].sub = 500;
// El original NO se ve afectadoconsole.log(originalProfundo[1][0].sub); // Muestra 20console.log(copiaProfunda[1][0].sub); // Muestra 500Limitaciones: Este método no funciona bien con ciertos tipos de datos como Date, RegExp, Map, Set, funciones, o undefined, ya que se pierden o transforman durante la serialización JSON.
2. Usando structuredClone() (Moderno)
La forma más moderna y robusta es usar la función global structuredClone().
let datosOriginales = [{ fecha: new Date() }, { set: new Set([1, 2]) }];let copiaEstructurada = structuredClone(datosOriginales);
// Modificamos el Set en la copiacopiaEstructurada[1].set.add(3);
// El original NO se ve afectadoconsole.log(datosOriginales[1].set); // Muestra Set(2) { 1, 2 }console.log(copiaEstructurada[1].set); // Muestra Set(3) { 1, 2, 3 }💡 structuredClone() es la mejor opción moderna para crear copias
profundas, ya que maneja más tipos de datos que el truco de JSON.
☝️🤓
🏋️♂️ Ejercicio
- Crea un arreglo
miArray = [5, 10, 15]. 2. Crea una referencia llamadarefArrayasignándolemiArray. 3. Crea una copia superficial llamadacopiaArrayusando el operador Spread. 4. ModificarefArrayagregando el número 20 al final (push(20)). 5. ModificacopiaArraycambiando el primer elemento a99(copiaArray[0] = 99). 6. Muestra por consolamiArray,refArrayycopiaArray. Explica por quémiArraycambió en un caso pero no en el otro.
🏋️♂️ Ejercicio
Dado el arreglo: let datos = [{ nombre: "Alice" }, { nombre: "Bob" }];
- Crea una copia superficial
copia1usandoslice(). - Crea una copia profunda
copia2usandostructuredClone(). - Cambia el nombre del primer objeto en
copia1a “Charlie” (copia1[0].nombre = "Charlie"). - Cambia el nombre del segundo objeto en
copia2a “David” (copia2[1].nombre = "David"). - Muestra por consola el arreglo
datosoriginal. ¿Cuál de las modificaciones (CharlieoDavid) afectó al original y por qué?
🚀 Extra
Investiga sobre: 1. Las limitaciones exactas del método
JSON.parse(JSON.stringify()) para copias profundas (qué tipos de datos no
maneja bien). 2. Bibliotecas de JavaScript populares (como Lodash) que ofrecen
funciones para realizar copias profundas (ej. _.cloneDeep()). ¿Qué ventajas
ofrecen sobre structuredClone() o el método JSON? 3. ¿Qué es la “copia por
valor” vs “copia por referencia” en JavaScript?
Comentarios
Roadmap
Dominando conceptos: Arreglos
Artículo 6 de 13