JavaScript tiene métodos de array menos conocidos pero muy útiles para tareas concretas: ordenar con criterio personalizado, acceder al último elemento de forma limpia, comprobar existencia incluso con NaN, crear arrays desde cualquier iterable y gestionar porciones de array. Conocerlos evita reinventar la rueda.
sort(): ordenar con función comparadora
sort() sin argumentos convierte los elementos a string y los ordena lexicográficamente, lo que da resultados incorrectos con números. Siempre hay que pasar una función comparadora:
// sort() sin comparadora: orden lexicográfico (incorrecto para números)
const nums = [10, 1, 21, 2, 100];
console.log(nums.sort()); // [1, 10, 100, 2, 21] INCORRECTO
// Con función comparadora:
// fn(a, b) < 0: a va antes; > 0: b va antes; = 0: mismo orden
nums.sort((a, b) => a - b); // ascendente
console.log(nums); // [1, 2, 10, 21, 100]
nums.sort((a, b) => b - a); // descendente
console.log(nums); // [100, 21, 10, 2, 1]
// Ordenar objetos por propiedad
const productos = [
{ nombre: 'Monitor', precio: 350 },
{ nombre: 'Teclado', precio: 89 },
{ nombre: 'Ratón', precio: 45 }
];
productos.sort((a, b) => a.precio - b.precio);
console.log(productos.map(p => p.nombre));
// ['Ratón', 'Teclado', 'Monitor']
// Ordenar strings: localeCompare para soporte de acentos y ñ
const nombres = ['Ángel', 'Ana', 'Álvaro', 'Beatriz', 'Óscar'];
nombres.sort((a, b) => a.localeCompare(b, 'es'));
console.log(nombres);
// ['Álvaro', 'Ana', 'Ángel', 'Beatriz', 'Óscar']
at(): acceso con índice negativo
El método at(índice) acepta índices negativos para contar desde el final, igual que Python. Es más claro que arr[arr.length - 1]:
const letras = ['a', 'b', 'c', 'd', 'e']; console.log(letras.at(0)); // 'a' primer elemento console.log(letras.at(-1)); // 'e' último elemento console.log(letras.at(-2)); // 'd' penúltimo console.log(letras.at(10)); // undefined (fuera de rango) // Comparación con el acceso clásico: const ultimo = letras[letras.length - 1]; // 'e' (verboso) const ultimoAt = letras.at(-1); // 'e' (limpio) // También funciona con strings y TypedArrays: const texto = 'JavaScript'; console.log(texto.at(-1)); // 't' console.log(texto.at(0)); // 'J'
includes() vs indexOf(): cuándo importa la diferencia
includes(valor) devuelve un booleano y maneja correctamente NaN. indexOf(valor) usa comparación estricta y no encuentra NaN:
const valores = [1, 2, NaN, 4, 5];
// includes: correcto con NaN
console.log(valores.includes(NaN)); // true
console.log(valores.includes(3)); // false
console.log(valores.includes(1, 2)); // false (busca desde índice 2)
// indexOf: no encuentra NaN
console.log(valores.indexOf(NaN)); // -1 (incorrecto)
console.log(valores.indexOf(2)); // 1
// Cuándo usar indexOf: cuando necesitas la posición
const idx = valores.indexOf(4);
if (idx !== -1) {
valores.splice(idx, 1); // eliminar elemento por valor
}
// Cuándo usar includes: cuando solo necesitas saber si existe
const permitidos = ['admin', 'editor', 'viewer'];
if (permitidos.includes(rolUsuario)) {
// acceso permitido
}
Array.from(): crear arrays desde cualquier cosa
Array.from(iterable, mapFn) convierte cualquier iterable o array-like en un array real, con una función de transformación opcional:
// Desde un Set (eliminar duplicados)
const unicos = Array.from(new Set([1, 2, 2, 3, 3, 4]));
console.log(unicos); // [1, 2, 3, 4]
// Desde un string
const letras = Array.from('hola');
console.log(letras); // ['h', 'o', 'l', 'a']
// Desde NodeList (acceso DOM)
const parrafos = Array.from(document.querySelectorAll('p'));
parrafos.forEach(p => console.log(p.textContent));
// Crear array de N elementos con transformación
const cuadrados = Array.from({ length: 5 }, (_, i) => (i + 1) ** 2);
console.log(cuadrados); // [1, 4, 9, 16, 25]
const rango = Array.from({ length: 10 }, (_, i) => i);
console.log(rango); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
splice() vs slice(): la diferencia que más confunde
splice() modifica el array original; slice() devuelve una copia sin modificar el original:
const arr = [1, 2, 3, 4, 5];
// slice(inicio, fin): extrae sin modificar
const porcion = arr.slice(1, 3);
console.log(porcion); // [2, 3]
console.log(arr); // [1, 2, 3, 4, 5] sin cambios
// slice con negativos
console.log(arr.slice(-2)); // [4, 5]
console.log(arr.slice(1, -1)); // [2, 3, 4]
// splice(inicio, eliminar, ...insertar): modifica el original
const arr2 = [1, 2, 3, 4, 5];
const eliminados = arr2.splice(1, 2, 'a', 'b', 'c');
console.log(eliminados); // [2, 3] (lo que se eliminó)
console.log(arr2); // [1, 'a', 'b', 'c', 4, 5]
// splice para eliminar un elemento concreto
const lista = ['rojo', 'verde', 'azul'];
const idx = lista.indexOf('verde');
if (idx !== -1) lista.splice(idx, 1);
console.log(lista); // ['rojo', 'azul']
La regla mnemotécnica: slice no cambia el original (como hacer una foto); splice lo destruye y reconstruye (corta y pega).
