Menu

Funciones de orden superior en JavaScript: map, filter y reduce

Aprende qué son las funciones de orden superior en JavaScript: cómo pasar funciones como argumentos, devolverlas desde otras funciones y dominar map, filter y reduce con ejemplos reales.

Las funciones son valores

En JavaScript, una función es un valor como cualquier otro. Puedes guardarla en una variable, meterla en un array, pasarla a otra función o devolverla desde una. Ese simple hecho abre la puerta a todo un estilo de programación:

index.js
Output
Click Run to see the output here.

Cuando asimilas que las funciones son valores como cualquier otro, las funciones de orden superior dejan de parecer un concepto abstracto. Una función de orden superior (higher-order function) es, sencillamente, una función que recibe otra función como argumento, devuelve una función, o ambas cosas a la vez. Esa es toda la definición.

Pasar una función como argumento

La forma más habitual: una función que acepta un callback y se encarga de ejecutarlo por ti. Seguro que ya las has usado mil veces sin darte cuenta.

index.js
Output
Click Run to see the output here.

forEach es una función de orden superior: recibe tu función y la ejecuta una vez por cada elemento. setTimeout también lo es: recibe tu función y la llama después de un tiempo. Tú te concentras en el qué hacer; ellas se encargan del cuándo y cuántas veces.

Crear las tuyas propias sigue la misma lógica. Aquí tienes una función mínima que ejecuta un callback solo si se cumple una condición:

index.js
Output
Click Run to see the output here.

action es un parámetro que casualmente guarda una función. Al invocarlo con action() ejecutas lo que se haya pasado.

Las tres que vas a usar sí o sí: map, filter y reduce

Los arrays en JavaScript traen métodos de orden superior que sustituyen a la mayoría de los bucles for que escribirías a mano. Domina estos tres y verás cómo buena parte del código del día a día se vuelve más corto y claro.

map — transformar cada elemento

index.js
Output
Click Run to see the output here.

map llama a tu función una vez por cada elemento y junta los valores devueltos en un nuevo array. Misma longitud, contenido transformado. El array original no se toca.

filter — quédate solo con los que cumplen la condición

index.js
Output
Click Run to see the output here.

filter se queda con los elementos cuyo callback devuelve un valor truthy y descarta el resto. Devuelve un array nuevo, que puede ser más corto.

reduce — plegar el array en un solo valor

index.js
Output
Click Run to see the output here.

reduce es el más versátil de los tres. El callback recibe el acumulador y el elemento actual; lo que retornes pasa a ser el siguiente acumulador. El segundo argumento (aquí 0) es el valor inicial.

Además, puedes encadenarlos. Aquí es donde este estilo realmente brilla:

index.js
Output
Click Run to see the output here.

Se lee de corrido: quedarse con los pedidos pagados, sacar el precio y sumarlo todo. Sin bucles, sin contadores mutables y sin preocuparse por el típico off-by-one.

Devolver una función desde otra función en JavaScript

La otra mitad de las funciones de orden superior. Una función que construye y devuelve otra función:

index.js
Output
Click Run to see the output here.

multiplyBy(2) se ejecuta una sola vez y te devuelve una función totalmente nueva. Esa función sigue acordándose de factor: eso es un closure, y le dedicaremos una página más adelante. Por ahora, quédate con esta idea: si llamas a multiplyBy con distintos argumentos, obtienes funciones especializadas distintas, todas creadas a partir de la misma plantilla.

Este patrón aparece por todas partes:

index.js
Output
Click Run to see the output here.

Una única definición y dos funciones reutilizables. Mucho mejor que escribir warn e info a mano y tener que mantenerlas sincronizadas.

Funciones con nombre vs callbacks en línea

En JavaScript puedes pasar una función flecha en línea o pasar una función por su nombre. Las dos opciones funcionan igual de bien, así que elige la que se lea mejor:

index.js
Output
Click Run to see the output here.

Cuando pasas isEven (sin paréntesis), lo que entregas es la función en sí. Si le añades (), la estarías ejecutando al instante y pasarías el resultado — un error clásico cuando recién empiezas:

nums.filter(isEven);     // correct: passes the function
nums.filter(isEven());   // wrong: calls isEven with no args, passes the result

Si el callback empieza a extenderse más allá de un par de líneas, sácalo y ponle un nombre. El código que lo rodea casi siempre gana en claridad.

Un ejemplo práctico

Las funciones de orden superior en JavaScript brillan cuando compones piezas pequeñas. Imagina que tienes una lista de productos y quieres obtener los nombres de los artículos baratos que estén en stock, en mayúsculas:

index.js
Output
Click Run to see the output here.

Cada función auxiliar hace una sola cosa. Cada método de array aplica una sola transformación. El pipeline se lee como la especificación de lo que quieres, no como una descripción de cómo iterar.

Cuándo no conviene usarlas

Las funciones de orden superior en JavaScript son geniales, pero no sirven para reemplazar cualquier bucle:

  • Si necesitas cortar a mitad de camino, un for o for...of con break queda más claro que intentar salirte de un forEach.
  • Si dentro del callback hay código asíncrono, map y forEach no van a esperar a que resuelva. Usa for...of con await, o bien Promise.all junto con map.
  • Si el callback está mutando estado compartido, te estás alejando de las ventajas de este estilo. Mejor tira de un bucle normal o refactoriza para que devuelva valores nuevos.

Aplicados donde encajan, map, filter y reduce se llevan por delante casi todo el boilerplate de bucles del día a día. Aplicados en todas partes, empiezan a perjudicar la legibilidad. Elige la herramienta que deje más clara la intención.

Siguiente: objetos

Las funciones no son los únicos valores sobre los que merece la pena construir. Los objetos son la pieza estrella de JavaScript para agrupar datos y comportamiento relacionados, y son justo lo que había dentro de la mayoría de los arrays que acabas de filtrar y mapear. Eso lo vemos en la siguiente página.

Preguntas frecuentes

¿Qué es una función de orden superior en JavaScript?

Una función de orden superior es aquella que cumple al menos una de estas dos condiciones: recibe otra función como argumento o devuelve una función como resultado. Array.prototype.map, setTimeout y addEventListener son ejemplos claros: todas aceptan un callback y lo ejecutan por ti cuando toca.

¿Cuál es la diferencia entre map, filter y reduce?

map transforma cada elemento y devuelve un array nuevo del mismo tamaño. filter se queda con los elementos cuyo callback devuelve un valor truthy, así que devuelve un array igual o más corto. reduce condensa todo el array en un único valor combinando los elementos uno a uno. Las tres son funciones de orden superior porque reciben un callback.

¿Por qué devolver una función desde otra función?

Para crear helpers pequeños y configurables sin repetir lógica. Por ejemplo, multiplyBy(n) devuelve una nueva función que multiplica por n, de modo que multiplyBy(2) y multiplyBy(10) te dan dos funciones especializadas a partir de una sola definición. Este patrón se apoya en los closures y es muy habitual en manejadores de eventos, middleware y librerías de utilidades.

Aprende a programar con Coddy

COMENZAR