Tema
Métodos de arrays
En proyectos reales casi todo es una lista: productos, usuarios, pedidos, comentarios. Los métodos de arrays te permiten transformar, filtrar, buscar y resumir esas listas en una sola línea, sin escribir bucles for a mano. Son la herramienta que más vas a usar en JavaScript moderno (y en React, Vue o Node).
Concepto
Piensa en un array como una banda transportadora de una fábrica. Cada método es una estación:
maptransforma cada caja (le pone etiqueta, la pinta).filterdeja pasar sólo las cajas que cumplen una condición.reducejunta todas las cajas en un solo resultado (un total, un objeto).findbusca la primera caja que cumple la condición y se detiene.
Todos reciben una función callback que se ejecuta por cada elemento. Esa función recibe tres argumentos: el elemento, su índice y el array completo (casi siempre sólo usas el primero).
js
const numeros = [1, 2, 3, 4];
numeros.map((numero, indice, arrayCompleto) => {
console.log(numero, indice, arrayCompleto);
return numero * 2;
});Métodos que NO modifican vs. que SÍ modifican
map, filter, reduce, find, some, every, slice, flat y concat devuelven algo nuevo y no tocan el array original. sort, reverse, splice, push, pop, shift, unshift y fill modifican el array original. En ES2023 existen versiones que no mutan: toSorted, toReversed y toSpliced.
Los datos de ejemplo
Usaremos este catálogo durante toda la lección:
js
const productos = [
{ id: 1, nombre: 'Laptop', precio: 15999, categoria: 'computo', stock: 4 },
{ id: 2, nombre: 'Mouse', precio: 349, categoria: 'accesorios', stock: 25 },
{ id: 3, nombre: 'Teclado mecánico', precio: 1299, categoria: 'accesorios', stock: 0 },
{ id: 4, nombre: 'Monitor 27"', precio: 4899, categoria: 'computo', stock: 7 },
{ id: 5, nombre: 'Audífonos', precio: 899, categoria: 'audio', stock: 12 }
];forEach: recorrer
forEach ejecuta una función por cada elemento. No devuelve nada (undefined). Úsalo cuando sólo quieras "hacer algo" con cada elemento: imprimir, pintar en el DOM, enviar datos.
js
productos.forEach((producto) => {
console.log(`${producto.nombre}: $${producto.precio}`);
});Error común
No puedes usar break dentro de forEach. Si necesitas detenerte antes, usa un for...of, o bien find/some, que se detienen solos al encontrar lo que buscan.
map: transformar
map devuelve un array nuevo del mismo tamaño, con lo que retorne tu función para cada elemento.
js
// Sólo los nombres
const nombres = productos.map((p) => p.nombre);
// ['Laptop', 'Mouse', 'Teclado mecánico', 'Monitor 27"', 'Audífonos']
// Precios con IVA (16 %)
const conIva = productos.map((p) => ({
...p, // copiamos todas las propiedades
precioConIva: Math.round(p.precio * 1.16)
}));
// Generar HTML a partir de datos (muy usado con el DOM)
const html = productos
.map((p) => `<li>${p.nombre} - $${p.precio}</li>`)
.join('');Buena práctica
Si devuelves un objeto en una función flecha de una línea, envuélvelo en paréntesis: p => ({ nombre: p.nombre }). Sin paréntesis, JavaScript interpreta las llaves como el cuerpo de la función y devuelve undefined.
filter: quedarte con algunos
filter devuelve un array nuevo sólo con los elementos para los que tu función devuelve true.
js
const disponibles = productos.filter((p) => p.stock > 0);
const accesorios = productos.filter((p) => p.categoria === 'accesorios');
const baratos = productos.filter((p) => p.precio < 1000);
// Buscador: nombre que contenga el texto, sin importar mayúsculas
function buscar(texto) {
const t = texto.toLowerCase().trim();
return productos.filter((p) => p.nombre.toLowerCase().includes(t));
}
buscar('mo'); // Mouse y Monitor 27"find y findIndex: buscar uno
find devuelve el primer elemento que cumple la condición, o undefined si no hay ninguno. findIndex devuelve su posición, o -1.
js
const mouse = productos.find((p) => p.id === 2);
console.log(mouse.nombre); // 'Mouse'
const noExiste = productos.find((p) => p.id === 99);
console.log(noExiste); // undefined
const posicion = productos.findIndex((p) => p.id === 4); // 3También existen findLast y findLastIndex, que buscan desde el final.
Error común
find puede devolver undefined. Si haces productos.find(...).nombre y no lo encuentra, tu app truena con Cannot read properties of undefined. Protégete con optional chaining: productos.find(p => p.id === id)?.nombre.
some y every: preguntas de sí o no
js
// ¿Hay ALGÚN producto agotado?
const hayAgotados = productos.some((p) => p.stock === 0); // true
// ¿TODOS cuestan menos de 20 mil?
const todosAccesibles = productos.every((p) => p.precio < 20000); // trueSon ideales para validaciones: "¿todos los campos están llenos?", "¿algún producto del carrito ya no tiene stock?".
reduce: resumir en un solo valor
reduce es el más poderoso y el que más cuesta al inicio. Recorre el array llevando un acumulador que vas actualizando.
js
array.reduce((acumulador, elemento) => {
// devuelve el nuevo valor del acumulador
}, valorInicial);Sumar un total
js
const valorInventario = productos.reduce((total, p) => {
return total + p.precio * p.stock;
}, 0);Paso a paso con un ejemplo más pequeño:
| Vuelta | acumulador | elemento | retorno |
|---|---|---|---|
| 1 | 0 | 10 | 10 |
| 2 | 10 | 20 | 30 |
| 3 | 30 | 5 | 35 |
js
[10, 20, 5].reduce((acc, n) => acc + n, 0); // 35Agrupar por categoría
js
const porCategoria = productos.reduce((grupos, p) => {
// si la categoría aún no existe, la creamos como array vacío
grupos[p.categoria] ??= [];
grupos[p.categoria].push(p.nombre);
return grupos;
}, {});
// { computo: ['Laptop', 'Monitor 27"'], accesorios: [...], audio: ['Audífonos'] }Novedad
Los navegadores modernos ya incluyen Object.groupBy(productos, p => p.categoria), que hace exactamente esto. Es bueno conocer las dos formas.
Contar ocurrencias
js
const votos = ['si', 'no', 'si', 'si', 'no'];
const conteo = votos.reduce((acc, voto) => {
acc[voto] = (acc[voto] || 0) + 1;
return acc;
}, {});
// { si: 3, no: 2 }Error común
Olvidar el valor inicial (0, {}, []). Sin él, reduce usa el primer elemento como acumulador, lo que en arrays de objetos produce resultados raros como "[object Object]349...", y con arrays vacíos lanza un error.
sort: ordenar
sort modifica el array original y, por defecto, ordena como texto. Eso produce sorpresas con números:
js
[10, 9, 100, 1].sort(); // [1, 10, 100, 9] ← ¡orden alfabético!Siempre pasa una función comparadora: devuelve un número negativo si a va antes, positivo si b va antes y 0 si son iguales.
js
const numeros = [10, 9, 100, 1];
numeros.sort((a, b) => a - b); // ascendente: [1, 9, 10, 100]
numeros.sort((a, b) => b - a); // descendente: [100, 10, 9, 1]
// Ordenar productos por precio SIN modificar el original
const porPrecio = [...productos].sort((a, b) => a.precio - b.precio);
// o en navegadores modernos:
const porPrecio2 = productos.toSorted((a, b) => a.precio - b.precio);
// Ordenar texto con acentos correctamente (español)
const porNombre = productos.toSorted((a, b) =>
a.nombre.localeCompare(b.nombre, 'es')
);flat, flatMap, includes, join
js
// flat: aplana arrays anidados
[[1, 2], [3, [4]]].flat(); // [1, 2, 3, [4]]
[[1, 2], [3, [4]]].flat(Infinity); // [1, 2, 3, 4]
// flatMap: map + flat de un nivel
const pedidos = [
{ cliente: 'Ana', items: ['Mouse', 'Teclado'] },
{ cliente: 'Luis', items: ['Laptop'] }
];
const todosLosItems = pedidos.flatMap((p) => p.items);
// ['Mouse', 'Teclado', 'Laptop']
// includes: ¿existe el valor?
['admin', 'editor'].includes('admin'); // true
// join: unir en un string
['HTML', 'CSS', 'JS'].join(' · '); // 'HTML · CSS · JS'Encadenar métodos
Como map y filter devuelven arrays, puedes encadenarlos. Lee la cadena como una receta, de arriba hacia abajo:
js
// Total a pagar de los accesorios disponibles, con IVA
const total = productos
.filter((p) => p.categoria === 'accesorios') // 1. sólo accesorios
.filter((p) => p.stock > 0) // 2. con stock
.map((p) => p.precio * 1.16) // 3. precio con IVA
.reduce((suma, precio) => suma + precio, 0); // 4. sumar
console.log(total.toFixed(2)); // '404.84'Buena práctica
Pon cada método en su propia línea y usa nombres descriptivos en los callbacks (producto, usuario) cuando la cadena sea larga. Tu yo del futuro te lo agradecerá.
Demo en vivo
Un catálogo con buscador, filtro por categoría, orden por precio y total calculado con reduce. Edita el código y observa cómo cambia:
Casos de uso reales
js
// 1. Eliminar un elemento por id (inmutable) — típico en apps de tareas
const sinMouse = productos.filter((p) => p.id !== 2);
// 2. Actualizar un elemento por id (inmutable)
const actualizados = productos.map((p) =>
p.id === 3 ? { ...p, stock: 10 } : p
);
// 3. Quitar duplicados
const categorias = [...new Set(productos.map((p) => p.categoria))];
// ['computo', 'accesorios', 'audio']
// 4. Promedio
const promedio =
productos.reduce((acc, p) => acc + p.precio, 0) / productos.length;
// 5. El más caro
const masCaro = productos.reduce((max, p) => (p.precio > max.precio ? p : max));
// 6. Convertir array a objeto indexado por id (búsquedas rápidas)
const porId = Object.fromEntries(productos.map((p) => [p.id, p]));
porId[4].nombre; // 'Monitor 27"'¿Cuál uso?
| Quiero... | Método |
|---|---|
| Hacer algo con cada elemento | forEach |
| Un array nuevo transformado | map |
| Un array con sólo algunos | filter |
| Un solo elemento | find |
| Su posición | findIndex |
| Saber si alguno cumple | some |
| Saber si todos cumplen | every |
| Un total, un objeto o un único valor | reduce |
| Ordenar | toSorted / [...arr].sort |
Ejercicios
Usa el array productos de esta lección.
- Obtén un array con los nombres en MAYÚSCULAS de los productos que cuestan más de 1000.
- Calcula cuántas unidades hay en total en el inventario (suma de
stock). - Escribe una función
obtenerPorId(id)que devuelva el nombre del producto o'No encontrado'. - Crea un array de strings con el formato
"Laptop ($15,999)"ordenado del más barato al más caro, sin modificarproductos. - Usa
reducepara obtener un objeto con el precio total por categoría:{ computo: 20898, accesorios: 1648, audio: 899 }.
Ver solución
js
// 1
const caros = productos
.filter((p) => p.precio > 1000)
.map((p) => p.nombre.toUpperCase());
// 2
const unidades = productos.reduce((total, p) => total + p.stock, 0); // 48
// 3
function obtenerPorId(id) {
return productos.find((p) => p.id === id)?.nombre ?? 'No encontrado';
}
// 4
const etiquetas = productos
.toSorted((a, b) => a.precio - b.precio)
.map((p) => `${p.nombre} ($${p.precio.toLocaleString('es-MX')})`);
// 5
const totalPorCategoria = productos.reduce((acc, p) => {
acc[p.categoria] = (acc[p.categoria] ?? 0) + p.precio;
return acc;
}, {});Resumen
- Los métodos de arrays reciben un callback que se ejecuta por cada elemento.
maptransforma,filterfiltra,findbusca uno,some/everyresponden sí o no yreduceresume.sortmodifica el original y ordena como texto: usa siempre un comparador y copia antes ([...arr]otoSorted).- Encadena métodos para escribir "recetas" de datos legibles.
- Para actualizar o eliminar sin mutar:
mapcon ternario yfiltercon!==.
Siguiente: Objetos