Ir al contenido
wannacode

Arrays: push, splice y sort

En resumen: Un array en JavaScript también es una lista: push añade al final, splice quita elementos sin dejar huecos, y sort lo ordena, pero los números como texto si no le das una función.

Problema

El carrito está lleno

Estás escribiendo el carrito de compras de una tienda en línea, y guardas los productos en un array, como en la lección sobre arrays: cada producto en su propio índice. JavaScript te deja escribir también más allá del final, pero tienes que llevar la cuenta del primer índice libre. Y cuando el cliente quita un producto, queda un hueco:

const cart = ["Pan", "Leche", "Café"];
// Un cuarto producto: escribimos en el primer índice libre.
cart[cart.length] = "Mantequilla";
// El cliente quita la leche.
cart[1] = undefined;
for (const item of cart) {
console.log(item);
}
console.log(cart.length);
Salida
Pan
undefined
Café
Mantequilla
4
Ahora cada bucle sobre el carrito tiene que saltarse undefined. Y el número de productos ya no es cart.length: eso es 4, pero hay 3 productos.

Es mucho código para algo que toda tienda hace todo el tiempo.

La idea

push y splice: el array se cuida solo

El array tiene métodos que hacen esto por ti. Copia y desplaza solo. Una colección que crece y se encoge así se llama lista, y en JavaScript es el propio array:

const cart = [];
cart.push("Pan");
cart.push("Leche");
cart.push("Café");
cart.push("Mantequilla");
cart.splice(cart.indexOf("Leche"), 1);
console.log(cart);
console.log(`Productos: ${cart.length}`);
Salida
[ 'Pan', 'Café', 'Mantequilla' ]
Productos: 3
  • push añade al final.
  • No hay un método que quite por valor. indexOf encuentra el índice de «Leche», y splice(index, 1) quita un elemento desde ahí y cierra el hueco: «Café» pasa al lugar de «Leche».
  • length es cuántos elementos hay ahora mismo.
  • console.log imprime todo el array entre corchetes, con el texto entre comillas.

Esto es lo que hace el array por dentro. Tú no eliges cuántos lugares tiene. Lo decide el motor que ejecuta el código (V8 en Node y en Chrome). Un array de 3 productos escrito en el código tiene exactamente 3 lugares, así que se llena con el cuarto:

const cart = ["Pan", "Leche", "Café"];
cart.push("Mantequilla");
cart.splice(cart.indexOf("Leche"), 1);
console.log(cart);
console.log(`Productos: ${cart.length}`);
Paso a paso, en palabras
  1. cart apunta a un array. Por dentro tiene length y un array aparte, elements, con 3 lugares.
  2. Los productos del código llenan los lugares uno a uno. El array está lleno: 3 de 3.
  3. No hay sitio. push crea un array con 22 lugares y copia en él los elementos.
  4. Ahora elements apunta al array nuevo, y el viejo ya no lo necesita nadie. «Mantequilla» va al lugar libre.
  5. splice quita «Leche», y todo lo que viene después se mueve un lugar a la izquierda. No queda ningún hueco.
  6. Desde fuera solo ves un array de tres productos. El motor V8 decide cuántos lugares tiene por dentro: el lenguaje no lo promete.
Más precisamente, para curiosos
  • También existe delete cart[1], pero no desplaza nada. Deja un hueco, y length sigue igual:
const cart = ["Pan", "Leche", "Café"];
delete cart[1];
console.log(cart, cart.length);
Salida
[ 'Pan', <1 empty item>, 'Café' ] 3

Para un array, usa splice.

La idea

Qué va en un array

Un array no pregunta qué pones en él. Un texto y un número pueden estar uno al lado del otro:

const cart = [];
cart.push("Pan");
cart.push(5);
console.log(cart);
Salida
[ 'Pan', 5 ]

Parece práctico, pero el error aparece más tarde, donde esperas texto. Por eso un array guarda un solo tipo de cosa: solo productos, solo precios.

JavaScript por sí mismo no tiene forma de decir «un array solo de texto». Eso lo hace TypeScript. Es JavaScript con tipos: allí un array de texto es string[], y cart.push(5) es un error directamente en el editor.

La idea

Índices: [i], splice, indexOf, includes

Un array tiene índices del 0 a tasks.length - 1. Lees y reemplazas con [ ], e insertas con splice:

const tasks = ["Factura de marzo", "Llamar al banco", "Informe del almacén"];
console.log(tasks[0]);
tasks[1] = "Reunión en el banco";
tasks.splice(0, 0, "Café con el equipo");
console.log(tasks.join(", "));
console.log(tasks.indexOf("Informe del almacén"));
console.log(tasks.includes("Llamar al banco"));
Salida
Factura de marzo
Café con el equipo, Factura de marzo, Reunión en el banco, Informe del almacén
3
false
  • tasks[i] lee, y tasks[i] = x reemplaza.
  • splice(i, 0, x) inserta en el índice i y desplaza el resto a la derecha. El cero significa «no quitar nada».
  • indexOf(x) busca y devuelve el índice o -1, e includes(x) solo dice si está.
  • join(", ") une los elementos en un solo texto, separados por comas.
Más precisamente, para curiosos
  • Un índice fuera del array no detiene el programa. Da undefined. at(-1) cuenta desde atrás y da el último elemento:
const tasks = ["Factura de marzo", "Llamar al banco", "Informe del almacén"];
console.log(tasks[3]);
console.log(tasks.at(-1));
console.log(tasks.indexOf("Nóminas"));
Salida
undefined
Informe del almacén
-1
  • includes e indexOf comparan con ===. El texto es un valor, así que encuentran un texto igual.
  • Insertar y quitar al principio es lento en un array grande: cada elemento después del índice se mueve un lugar. Con un millón de elementos, son un millón de movimientos.

Pruébalo

¿Quién sigue?

La lista de pacientes que esperan en el médico. Juan entra, y Ana tiene cita, así que ocupa el segundo lugar.

¿Qué imprimirá el programa?

const waiting = ["Juan", "María", "Pedro"];
waiting.shift();
waiting.splice(1, 0, "Ana");
console.log(waiting, waiting.length);
Respuesta

La idea

Recorrer los elementos

Recorres un array con for...of cuando solo necesitas los elementos, o con un índice cuando también necesitas el número:

const cart = ["Pan", "Café", "Mantequilla"];
for (const item of cart) {
console.log(`- ${item}`);
}
for (let i = 0; i < cart.length; i++) {
console.log(`${i + 1}. ${cart[i]}`);
}
Salida
- Pan
- Café
- Mantequilla
1. Pan
2. Café
3. Mantequilla
Más precisamente, para curiosos
  • No quites elementos de un array mientras lo recorres con for...of. El programa no se detiene, pero se salta elementos:
const cart = ["Pan", "Pan", "Leche"];
for (const item of cart) {
if (item === "Pan") {
cart.splice(cart.indexOf(item), 1);
}
}
console.log(cart);
Salida
[ 'Pan', 'Leche' ]

El segundo «Pan» se quedó. splice desplazó todo a la izquierda, y el bucle siguió desde el índice siguiente y nunca lo vio. No hay error, así que un fallo así es difícil de detectar.

  • Si tienes que quitar, recorre con un índice de atrás hacia delante. Así, quitar no desplaza los elementos que todavía no has comprobado:
const cart = ["Pan", "Pan", "Leche"];
for (let i = cart.length - 1; i >= 0; i--) {
if (cart[i] === "Pan") {
cart.splice(i, 1);
}
}
console.log(cart);
Salida
[ 'Leche' ]
En el módulo «JavaScript moderno» verás una forma más corta que crea un array nuevo solo con los elementos que quieres: filter.

La idea

Números en un array

Un array de puntuaciones es como un array de texto. El número está en el array tal cual:

const scores = [85, 64, 91];
let total = 0;
for (const score of scores) {
total += score;
}
console.log(`Media: ${total / scores.length}`);
Salida
Media: 80

JavaScript imprime 80, no 80.0: para él los números enteros y los decimales son el mismo tipo, number.

Más precisamente, para curiosos
  • Un número en JavaScript es un valor primitivo, no un objeto. Por eso === compara los valores, y dos números iguales son iguales. También existe un envoltorio, new Number(257), que crea un objeto, y dos objetos son distintos aunque guarden lo mismo:
const c = Number("257");
const d = Number("257");
console.log(c === d);
console.log(new Number(257) === new Number(257));
Salida
true
false

No necesitas new Number. Escribe los números directamente.

Pruébalo

Encuentra el error

Un teatro guarda los asientos ocupados en un array. Un cliente deja el asiento 2, y el programa debería imprimir [ 12, 7, 5 ]. En cambio imprime [ 12, 2, 5 ]. ¿Qué línea tiene el error?

Elige la línea con el error.

Más precisamente, para curiosos
const seats = [12, 7, 5];
seats.splice(seats.indexOf(2), 1);
console.log(seats);
Salida
[ 12, 7 ]

La idea

Ordenar y un array que no cambia

sort() ordena el array en el sitio. El texto sale en orden alfabético. Pero los números no salen por tamaño:

const cities = ["Sevilla", "Madrid", "Valencia"];
cities.sort();
console.log(cities);
const prices = [30, 5, 12];
prices.sort();
console.log(prices);
prices.sort(function (a, b) {
return a - b;
});
console.log(prices);
Salida
[ 'Madrid', 'Sevilla', 'Valencia' ]
[ 12, 30, 5 ]
[ 5, 12, 30 ]

Sin una regla, sort convierte todo en texto y compara el texto. «12» va antes que «30», y «30» antes que «5», como en un diccionario. Así que a los números les das una regla: una función que recibe dos números y devuelve a - b. Un resultado negativo significa «a va antes que b». Por ahora, cópiala. En la lección «Clases anidadas» verás cómo escribir reglas así.

Un array que no cambia se crea con Object.freeze. Es inmutable: no puedes añadir, quitar ni ordenar en él.

const days = Object.freeze(["lun", "mar", "mié"]);
days.push("jue");
Error
TypeError: Cannot add property 3, object is not extensible

const no basta para esto: solo impide que days apunte a otro array, mientras que el propio array todavía puede cambiar.

Más precisamente, para curiosos
  • El texto se ordena por los códigos de sus caracteres. Las mayúsculas van antes que las minúsculas, así que «Pera» va antes que «manzana»:
const fruit = ["manzana", "Pera", "banana", "Uva"];
fruit.sort();
console.log(fruit);
Salida
[ 'Pera', 'Uva', 'banana', 'manzana' ]
  • toSorted() devuelve un array nuevo, ordenado, y no toca el viejo:
const prices = [30, 5, 12];
const cheapFirst = prices.toSorted(function (a, b) {
return a - b;
});
console.log(cheapFirst, prices);
Salida
[ 5, 12, 30 ] [ 30, 5, 12 ]
  • Cómo ordenar tus propios objetos, por ejemplo productos por precio, lo verás en la lección «Clases anidadas».

Ejercicio

Arrays en clases

Resuelve las tareas en tu editor. El array es un campo privado de la clase (#books), y el código debajo de las clases solo llama a sus métodos.

1. Una estantería. Una clase BookShelf con un método addBook(title) que pone el libro al final, y takeBook(), que devuelve y quita el primer libro (o null si la estantería está vacía). Añade count() y toString(). Añade «Bajo el yugo», «Tabaco» y «El candelabro de hierro», toma un libro e imprime el resto.

Salida
Tomado: Bajo el yugo
2 quedan: [Tabaco, El candelabro de hierro]

2. Un registro de eventos. Una clase Event con una fecha y una descripción, y una clase EventLog con los métodos addEvent(date, description) y getEventsBetween(from, to), que devuelve un array con los eventos entre las dos fechas, incluidas. Las fechas son texto con la forma 2026-03-31. Con esta forma, el texto se ordena igual que las fechas, así que <= y >= las comparan correctamente. Añade cuatro eventos: 2026-01-15 «Inventario anual», 2026-03-31 «Informe del primer trimestre», 2026-05-20 «Nuevo proveedor de café», 2026-09-01 «Nuevo curso escolar». Imprime los del 2026-03-01 al 2026-06-30.

Salida
2026-03-31 Informe del primer trimestre
2026-05-20 Nuevo proveedor de café

3. Un cuaderno. Una clase Note con un título y un contenido, y una clase Notebook con los métodos addNote, findNote(title) (devuelve la nota o null), deleteNote(title) (devuelve true si borró algo) y count(). Añade las notas «POO», «Colecciones» y «SQL», busca «Colecciones», borra «POO» y comprueba que ya no está.

Salida
Colecciones: el array crece solo
Borrada: POO
Notas: 2
No hay ninguna nota de POO.

4. Cálculo mental. Una clase Question con un texto y la respuesta correcta, y una clase MathGame con un array de preguntas, un método addQuestion y un método start(). start hace las preguntas una a una, lee la respuesta y al final dice cuántas fueron correctas. Las preguntas son 2 + 2, 3 * 4 y 15 - 9.

start lee con ask de la lección sobre la entrada, así que es async start(), y la llamada es await game.start(). Un método que espera la entrada se escribe así. Por ahora, cópialo.

Entrada
4
12
7
Salida
2 + 2 = ¡Correcto!
3 * 4 = ¡Correcto!
15 - 9 = Incorrecto, la respuesta es 6.
Puntuación: 2 de 3

Más tareas

  • Sin repetidos. Lee 6 nombres y reúnelos en un array, saltándote los que ya están. Para la entrada Juan, María, Juan, Ana, María, Pedro la salida es [ 'Juan', 'María', 'Ana', 'Pedro' ].
  • El producto más caro. Un array guarda precios. Encuentra el más alto y su índice, sin Math.max.
  • La lista al revés. Escribe una función que devuelva un array nuevo con los mismos elementos en orden inverso. No cambies el original.
  • Una lista de la compra. Lee las órdenes add milk, remove milk, list y end, y guarda la lista entre ellas. La orden de quitar un producto que no está dice «No existe ese producto.».

Test

Ponte a prueba

1. ¿Por qué push y splice son más prácticos que escribir por índice?
2. ¿Qué imprime console.log([30, 5, 12].sort())?
3. seats es [12, 2, 7, 5]. ¿Qué queda después de seats.splice(2, 1)?
4. tasks tiene 3 tareas. ¿Qué imprime console.log(tasks[3])?
5. const days = Object.freeze(["lun", "mar"]); ¿Qué pasa con days.push("mié")?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·