Funciones de Orden Superior en JavaScript: De lo Básico a lo Avanzado
En JavaScript, las funciones son ciudadanos de primera clase (first-class citizens). Esto permite tratarlas como valores: asignarlas a variables, pasarlas como argumentos y devolverlas desde otras funciones.
Una función de orden superior (HOF) es, precisamente, una función que recibe funciones como parámetros, devuelve funciones, o ambas.
🤔 ¿Qué son y por qué se usan?
Definición: Una HOF es una función que opera sobre funciones: las acepta o las produce.
Motivación:
- Abstraer patrones y generalizar comportamiento.
- Reutilizar y componer lógica de forma declarativa.
- Aislar efectos secundarios y mejorar la testeabilidad.
🧪 Ejemplos básicos
1) Pasar funciones como argumento
function aplicar(a, b, operacion) {
return operacion(a, b);
}
const sumar = (x, y) => x + y;
const multiplicar = (x, y) => x * y;
aplicar(3, 4, sumar); // 7
aplicar(3, 4, multiplicar); // 12
2) Devolver funciones (closures)
function crearMultiplicador(n) {
return function(x) {
return x * n;
};
}
const duplicar = crearMultiplicador(2);
duplicar(5); // 10
3) HOFs del core de arrays: map, filter, reduce
const nums = [1, 2, 3, 4, 5];
nums.map(n => n * 2); // [2, 4, 6, 8, 10]
nums.filter(n => n % 2 === 0); // [2, 4]
nums.reduce((acc, n) => acc + n, 0); // 15
🧩 Composición de funciones
La composición encadena funciones pequeñas para crear transformaciones más potentes.
// compose(f, g)(x) = f(g(x))
const compose = (...fns) => (x) => fns.reduceRight((v, f) => f(v), x);
// pipe(g, f)(x) = f(g(x)) pero de izquierda a derecha
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
const trim = (s) => s.trim();
const toUpper = (s) => s.toUpperCase();
const exclaim = (s) => s + "!";
const limpiarYEnfatizar = pipe(trim, toUpper, exclaim);
limpiarYEnfatizar(" hola "); // "HOLA!"
📈 ¿Cuándo son mejores las HOFs?
- Transformaciones de colecciones y pipelines de datos.
- Configuración y cross-cutting concerns (logging, permisos, caching).
- APIs declarativas en UI (React Hooks/props como funciones) y middleware.
- Control de flujo asíncrono (reintentos, backoff, debounce/throttle).
⚠️ Posibles inconvenientes
- Sobreabstracción: demasiadas capas ocultan la intención.
- Legibilidad: composición excesiva puede complicar el seguimiento.
- Rendimiento: en hot paths, demasiados closures/callbacks pueden penalizar.
- Depuración: stacks más profundos; nombra funciones cuando sea posible.