Trucos JavaScript: 12 atajos modernos que ahorran tiempo

Los mejores trucos de JavaScript no son magia negra: son funciones modernas que te ahorran líneas de código y errores tontos. Aquí tienes 12, ordenados de más útil a más avanzado.

Cada uno viene con su problema real, el código listo para copiar y el motivo por el que te conviene usarlo. Todo con sintaxis ES2023+, la que ya funciona en Node y en cualquier navegador actual. Si escribes JavaScript a diario, alguno de estos atajos va a entrar en tu rutina hoy mismo.

Por qué estos trucos JavaScript te ahorran tiempo

El lenguaje ha cambiado mucho desde ES6. Muchas cosas que antes resolvías con tres líneas y una función auxiliar hoy son una sola expresión nativa. Menos código propio significa menos bugs, menos dependencias y menos tiempo revisando lo que ya resuelve el motor.

1. Optional chaining (?.): acceso seguro sin reventar

El problema: accedes a una propiedad anidada y si un nivel intermedio no existe, salta el clásico Cannot read properties of undefined. El operador ?. corta la cadena y devuelve undefined en lugar de tirar todo abajo.

const user = { perfil: { nombre: "Ana" } };

// Sin optional chaining: error si no existe direccion
const ciudad = user?.direccion?.ciudad; // undefined, sin error

// También funciona con métodos y con índices
user.guardar?.();   // solo llama si guardar existe
const primero = lista?.[0];

Por qué te conviene: te libras de encadenar if y comprobaciones defensivas. Ideal para datos de una API que a veces vienen incompletos. Combínalo con el truco 2 y tienes acceso seguro con valor por defecto en una línea. Detalle en MDN.

2. Nullish coalescing (??): el valor por defecto que sí respeta el 0

El problema: usas || para poner un valor por defecto y te muerde con el 0, el "" o el false, porque son «falsy». El operador ?? solo entra cuando el valor es null o undefined.

const cantidad = 0;

const stock = cantidad ?? 10;    // 0  (correcto)
const stockMal = cantidad || 10; // 10 (bug silencioso)

Por qué te conviene: es de los bugs más difíciles de cazar, porque a veces funciona y a veces no. Usa ?? siempre que un valor legítimo pueda ser 0 o cadena vacía. Referencia en MDN.

3. at(-1): el último elemento sin contar la longitud

El problema: para el último elemento de un array escribes lista[lista.length - 1]. Funciona, pero es ruido. El método at() acepta índices negativos y lee desde el final.

const lista = ["a", "b", "c"];

const ultimo = lista.at(-1);   // "c"
const penultimo = lista.at(-2); // "b"

// También en strings
"hola".at(-1); // "a"

Por qué te conviene: se lee de un vistazo y evita repetir el nombre de la variable. Pequeño, pero lo vas a usar constantemente. Ver Array.prototype.at() en MDN.

4. Set: elimina duplicados de un array en una línea

El problema: quieres valores únicos de un array. Antes montabas un bucle con un objeto acumulador. Un Set solo guarda valores únicos, así que conviértelo y vuélvelo a array.

const numeros = [1, 2, 2, 3, 3, 3];

const unicos = [...new Set(numeros)]; // [1, 2, 3]

// Cuenta elementos distintos sin duplicar lógica
const distintos = new Set(numeros).size; // 3

Por qué te conviene: es rápido, legible y funciona con strings, números y referencias. Para tags, categorías o IDs repetidos es mi opción por defecto. Más en MDN.

Ejemplo de trucos JavaScript con Set para eliminar duplicados

5. Operadores de asignación lógica (??=, ||=, &&=)

El problema: quieres asignar un valor solo si la variable está vacía. Escribías if (!config.timeout) config.timeout = 3000;. Los operadores de asignación lógica lo comprimen.

const config = { timeout: undefined };

config.timeout ??= 3000; // asigna solo si es null/undefined
config.retries ||= 3;    // asigna si es "falsy"
config.debug &&= false;  // asigna solo si ya es "truthy"

Por qué te conviene: configuras opciones por defecto sin líneas if sueltas. El ??= es el más seguro porque, igual que el truco 2, respeta el 0 y la cadena vacía.

6. Destructuring con defaults y renombrado

El problema: extraer varias propiedades de un objeto, darles nombre nuevo y un valor por defecto, todo a la vez. El destructuring lo hace en una sola expresión.

const usuario = { nombre: "Ana", rol: "admin" };

// Renombra rol a permiso y pon defaults
const { nombre = "Anónimo", rol: permiso = "lector" } = usuario;

// Salta posiciones de un array
const [primero, , tercero] = ["a", "b", "c"];

// Parámetros con objeto por defecto (evita error si no pasas nada)
function crear({ ancho = 100, alto = 100 } = {}) {
  return { ancho, alto };
}

Por qué te conviene: firmas de funciones más limpias y menos variables intermedias. El truco del = {} al final evita que reviente cuando llamas a la función sin argumentos.

7. structuredClone: copia profunda de verdad

El problema: el spread {...obj} solo copia el primer nivel. El viejo truco JSON.parse(JSON.stringify(obj)) pierde Date, Map, Set y revienta con referencias circulares. structuredClone es la función nativa que clona en profundidad de forma correcta.

const original = {
  fecha: new Date(),
  tags: new Set(["js"]),
  meta: { anidado: true }
};

const copia = structuredClone(original);

copia.meta.anidado = false;
original.meta.anidado; // true (no se ha tocado)

Por qué te conviene: es global en navegadores modernos y en Node 17+. Se acabó importar una librería solo para clonar un objeto. Detalle en MDN.

8. Intl.NumberFormat: moneda y números bien formateados

El problema: mostrar precios con separadores de miles y símbolo de moneda correcto por región. Nada de concatenar strings a mano. Intl.NumberFormat lo resuelve según el idioma.

const precio = 1234.5;

const mxn = new Intl.NumberFormat("es-MX", {
  style: "currency",
  currency: "MXN"
}).format(precio); // "$1,234.50"

const eur = new Intl.NumberFormat("es-ES", {
  style: "currency",
  currency: "EUR"
}).format(precio); // "1234,50 €"

Por qué te conviene: respeta comas, puntos y posición del símbolo según el país sin que tú controles cada caso. Sirve también para porcentajes y unidades. Ver MDN.

9. Intl.RelativeTimeFormat: «hace 2 días» sin librerías

El problema: mostrar tiempos relativos tipo «hace 3 horas» o «en 2 días». Antes tirabas de una dependencia entera. Intl.RelativeTimeFormat lo hace nativo y traducido.

const rtf = new Intl.RelativeTimeFormat("es", { numeric: "auto" });

rtf.format(-2, "day");  // "anteayer"
rtf.format(-3, "hour"); // "hace 3 horas"
rtf.format(1, "week");  // "la próxima semana"

Por qué te conviene: el parámetro numeric: "auto" te da expresiones naturales como «ayer» en vez de «hace 1 día». Menos peso en el bundle y traducciones gratis. Más en MDN.

10. Object.groupBy: agrupa un array por clave

El problema: agrupar un array de objetos por una propiedad. El clásico reduce con acumulador funciona, pero es verboso. Object.groupBy (ES2024) lo hace en una llamada.

const productos = [
  { nombre: "Camiseta", tipo: "ropa" },
  { nombre: "Taza", tipo: "hogar" },
  { nombre: "Gorra", tipo: "ropa" }
];

const porTipo = Object.groupBy(productos, p => p.tipo);
// { ropa: [Camiseta, Gorra], hogar: [Taza] }

Por qué te conviene: el callback devuelve la clave y el método arma los grupos por ti. Es reciente, así que compruébalo en tu entorno: necesita Node 21+ o navegadores actuales. Referencia en MDN.

11. Promise.allSettled: varias peticiones sin que una tumbe al resto

El problema: lanzas varias promesas con Promise.all y, si una falla, pierdes todos los resultados. Promise.allSettled espera a todas y te dice cuáles salieron bien y cuáles no.

const resultados = await Promise.allSettled([
  fetch("/api/a"),
  fetch("/api/b"),
  fetch("/api/c")
]);

for (const r of resultados) {
  if (r.status === "fulfilled") console.log("OK", r.value);
  else console.warn("Falló", r.reason);
}

Por qué te conviene: perfecto cuando cargas datos de varias fuentes y quieres mostrar lo que sí llegó. Cada resultado trae su status, así que gestionas los fallos uno a uno. Ver MDN.

12. Array.from: genera secuencias sin bucles

El problema: necesitas un array de números del 1 al 10, o una rejilla de N elementos. En lugar de un for, Array.from acepta una longitud y una función de mapeo.

// Números del 1 al 10
const rango = Array.from({ length: 10 }, (_, i) => i + 1);

// 5 objetos vacíos con id
const filas = Array.from({ length: 5 }, (_, i) => ({ id: i }));

// Convierte un iterable (NodeList, string) en array real
const letras = Array.from("hola"); // ["h","o","l","a"]

Por qué te conviene: el segundo argumento es un map integrado, así que generas y transformas en un paso. Genial para paginación, calendarios o datos de prueba. Si aún encadenas map, filter y reduce, este cierra la caja de herramientas.

Recursos para seguir practicando

Los trucos se fijan usándolos. Aquí tienes por dónde seguir dentro del blog:

Preguntas frecuentes sobre trucos de JavaScript

¿Estos trucos JavaScript funcionan en todos los navegadores?

La mayoría sí: optional chaining, nullish coalescing, Set o destructuring llevan años en todos los navegadores actuales. Los más recientes, como Object.groupBy, necesitan versiones nuevas. Ante la duda, compruébalo en MDN o en tu propio entorno antes de subirlo a producción.

¿Qué significa ES2023 y por qué importa?

ES2023 es una edición del estándar ECMAScript, la especificación en la que se basa JavaScript. Cada año añade funciones nuevas. Usar sintaxis moderna te da código más corto y menos dependencias externas, siempre que tu entorno la soporte.

¿Cuándo uso ?? en lugar de ||?

Usa ?? cuando un valor legítimo pueda ser 0, cadena vacía o false. El operador || los trata como vacíos y mete el valor por defecto por error. El ?? solo actúa ante null o undefined.

¿structuredClone reemplaza a las librerías de clonado?

Para la mayoría de casos, sí. Clona objetos anidados, fechas, Map y Set sin dependencias. No copia funciones ni prototipos personalizados, así que para clases con métodos propios sigue evaluando tu caso concreto.

Guárdate esta lista y ve incorporando un truco por semana. Si te ha venido bien, compártela con quien esté aprendiendo JavaScript. Que lo disfrutes!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Scroll al inicio