Funciones de orden superior en JavaScript: callbacks y ejemplos
Actualizado el 29 de septiembre de 2026
En JavaScript una función es un valor más, como un número o un texto: se puede guardar en una variable, pasar como argumento a otra función o devolver desde una función. Una función de orden superior es la que recibe o devuelve otras funciones.
Ya las usaste si trabajaste con map, filter o sort. En esta guía vas a ver la idea detrás: cómo escribir tus propias funciones de orden superior, cómo crear funciones que fabrican otras funciones y los errores típicos al pasar callbacks.
Pasar una función como argumento
function aplicarDosVeces(fn, valor) {
return fn(fn(valor));
}
const doble = (x) => x * 2;
aplicarDosVeces(doble, 3); // 12
aplicarDosVeces((t) => t + "!", "hola"); // 'hola!!'aplicarDosVeces no sabe qué hace fn: solo sabe que es una función y la llama. Eso la hace reutilizable con cualquier transformación. A la función que se pasa como argumento se le llama callback.
Los métodos de array son funciones de orden superior
map, filter, find, some, reduce y sort reciben una función y la llaman por ti con cada elemento. Separan el recorrido (que siempre es igual) de lo que se hace con cada elemento (que cambia en cada caso):
[1, 2, 3].map(doble); // [2, 4, 6]
const personas = [
{ nombre: "Valentina", edad: 22 },
{ nombre: "Tomás", edad: 15 },
{ nombre: "Álvaro", edad: 30 },
];
const porEdad = (a, b) => a.edad - b.edad;
personas.toSorted(porEdad).map((p) => p.nombre);
// ['Tomás', 'Valentina', 'Álvaro']Devolver una función
Una función también puede crear y devolver otra función. Es una forma de fabricar funciones configuradas:
function crearMultiplicador(n) {
return (x) => x * n;
}
const triple = crearMultiplicador(3);
triple(5); // 15
crearMultiplicador(10)(4); // 40La función devuelta "recuerda" el valor de n con el que se creó, aunque crearMultiplicador ya haya terminado. Ese mecanismo se llama closure, y es la base de muchos patrones de JavaScript.
Componer funciones
function componer(f, g) {
return (x) => f(g(x));
}
const gritar = componer((t) => t + "!", (t) => t.toUpperCase());
gritar("hola"); // 'HOLA!'Componer es construir una función nueva a partir de otras más pequeñas: primero se aplica g y al resultado se le aplica f. El orden importa: con doble y sumarUno, componer(doble, sumarUno)(5) es 12, pero al revés es 11.
Callbacks que se ejecutan después
No todos los callbacks se ejecutan de inmediato. setTimeout(() => console.log("listo"), 1000) guarda la función y la llama un segundo después, mientras el resto del programa sigue. Lo mismo pasa con los eventos del navegador (boton.addEventListener("click", fn)): es la puerta de entrada a la programación asíncrona.
Errores comunes
Pasar el resultado en vez de la función
[1, 2, 3].map(doble(2));
// TypeError: number 4 is not a function
[1, 2, 3].map(doble); // correctoCon paréntesis, doble(2) se ejecuta en ese momento y se pasa su resultado, 4. Lo que hay que pasar es la función misma, sin paréntesis, para que map la llame con cada elemento.
El callback recibe más argumentos de los que crees
["1", "2", "3"].map(parseInt); // [1, NaN, NaN]
["1", "2", "3"].map(Number); // [1, 2, 3]map llama al callback con tres argumentos: el elemento, el índice y el array. parseInt usa el segundo como base numérica, así que parseInt("2", 1) y parseInt("3", 2) dan NaN. Si no estás seguro de qué parámetros acepta una función, envuélvela: map((t) => parseInt(t)).
Olvidar el return en el callback
[1, 2, 3, 4].filter((n) => { n % 2 === 0; }) devuelve []: con llaves, el callback devuelve undefined, que es falsy, y filter descarta todo. Quita las llaves o agrega return.
Ejercicios resueltos
Intenta resolver cada ejercicio antes de abrir la solución: equivocarse y corregir es la parte que más enseña.
1.Tu propio map
Escribe una función miMap(arreglo, fn) que funcione como arreglo.map(fn): devuelve un array nuevo con el resultado de llamar fn(elemento, indice) para cada elemento. No uses map.
miMap([1, 2, 3], (x) => x * 2)→[2, 4, 6]miMap(["a", "b"], (letra, i) => i + ":" + letra)→["0:a", "1:b"]miMap([], (x) => x)→[]
function miMap(arreglo, fn) {
// ...
}Ver soluciónOcultar solución
function miMap(arreglo, fn) {
const resultado = [];
for (let i = 0; i < arreglo.length; i++) {
resultado.push(fn(arreglo[i], i));
}
return resultado;
}map no tiene nada de mágico: recorre, llama la función y junta los resultados en un array nuevo. Se usa el for clásico porque hay que pasarle el índice al callback. Escribir tus propias versiones de map, filter o reduce es la mejor forma de entender qué hacen.
2.Componer dos funciones
Escribe una función componer(f, g) que devuelva una función nueva que, al recibir x, devuelva f(g(x)).
const doble = (x) => x * 2;
const sumarUno = (x) => x + 1;
componer(doble, sumarUno)(5); // → 12 (primero suma 1, después duplica)
componer(sumarUno, doble)(5); // → 11function componer(f, g) {
// ...
}Ver soluciónOcultar solución
function componer(f, g) {
return (x) => f(g(x));
}componer no calcula nada al llamarse: devuelve una función que calculará cuando reciba x. Esa función recuerda f y g gracias al closure. componer(doble, sumarUno)(5) tiene dos llamadas seguidas: la primera arma la función y la segunda la ejecuta con 5.
3.Fabricar filtros
Escribe una función filtrarPor(campo, valor) que devuelva una función que reciba un objeto y responda si objeto[campo] es igual a valor. Debe poder usarse directamente con filter.
const gente = [
{ nombre: "Ana", ciudad: "Santiago" },
{ nombre: "Luis", ciudad: "Talca" },
{ nombre: "Sofía", ciudad: "Santiago" },
];
gente.filter(filtrarPor("ciudad", "Santiago")).map((p) => p.nombre);
// → ["Ana", "Sofía"]function filtrarPor(campo, valor) {
// ...
}Ver soluciónOcultar solución
function filtrarPor(campo, valor) {
return (objeto) => objeto[campo] === valor;
}filter necesita una función que reciba un elemento y devuelva verdadero o falso. filtrarPor fabrica esa función con el campo y el valor ya fijados. El campo está en una variable, así que se lee con corchetes. El resultado es código que se lee casi como una frase: filtrar por ciudad igual a Santiago.