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);    // 40

La 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);   // correcto

Con 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) → []
Punto de partida
function miMap(arreglo, fn) {
  // ...
}
Ver solución
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)).

Ejemplo
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);   // → 11
Punto de partida
function componer(f, g) {
  // ...
}
Ver solución
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.

Ejemplo
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"]
Punto de partida
function filtrarPor(campo, valor) {
  // ...
}
Ver solución
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.

Practica JavaScript con ejercicios a tu nivel

En Coditer resuelves ejercicios en el navegador, con tests automáticos que revisan tu código y una IA que te da pistas cuando te atascas. Practicar es gratis.