Les fonctions sont des valeurs
En JavaScript, une fonction est une valeur comme une autre. Tu peux la ranger dans une variable, la glisser dans un tableau, la passer en argument à une autre fonction, ou encore la renvoyer depuis une autre. Ce simple fait ouvre la porte à tout un style de programmation :
Une fois qu'on est à l'aise avec l'idée que les fonctions sont des valeurs comme les autres, les fonctions d'ordre supérieur perdent tout leur côté mystérieux. Une fonction d'ordre supérieur (ou higher order function en anglais), c'est simplement une fonction qui prend une autre fonction en argument, qui en retourne une, ou les deux à la fois. Point final, c'est toute la définition.
Passer une fonction en argument
C'est le cas le plus courant : une fonction qui reçoit un callback et se charge de l'exécuter pour toi. Tu en as sûrement déjà utilisé sans même t'en rendre compte.
forEach est une fonction d'ordre supérieur : elle prend ta fonction et l'appelle une fois pour chaque élément. setTimeout aussi : elle prend ta fonction et l'exécute après un délai. Toi, tu te concentres sur quoi faire ; elles s'occupent du quand et du combien de fois.
Écrire la tienne, c'est pareil. Voici une petite fonction qui n'exécute un callback que si une condition est vraie :
action est un paramètre qui contient une fonction. L'appeler avec action() exécute ce qu'on lui a passé.
Les trois indispensables : map, filter et reduce
Les tableaux disposent de méthodes d'ordre supérieur qui remplacent la plupart des boucles for que tu écrirais autrement. Maîtrise ces trois-là et une bonne partie de ton code quotidien devient plus court et plus lisible.
map — transformer chaque élément
map appelle votre fonction une fois par élément et rassemble les valeurs de retour dans un nouveau tableau. Même longueur, contenu transformé. Le tableau d'origine, lui, reste intact.
filter — ne garder que ce qui correspond
filter ne garde que les éléments pour lesquels le callback renvoie une valeur truthy, et met de côté tous les autres. Le résultat est un nouveau tableau, potentiellement plus court que l'original.
reduce — condenser le tableau en une seule valeur
reduce est le couteau suisse du lot. Le callback reçoit l'accumulateur courant et l'élément en cours de traitement ; ce que tu renvoies devient le nouvel accumulateur. Le deuxième argument (0 ici) sert de valeur initiale.
Et le vrai plaisir, c'est de les chaîner. C'est là que ce style prend tout son sens :
On lit ça de haut en bas : on garde les commandes payées, on extrait le prix, on additionne le tout. Aucune boucle, aucun compteur mutable, aucun risque de décalage d'indice.
Retourner une fonction depuis une fonction
L'autre facette des fonctions d'ordre supérieur en JavaScript : une fonction qui construit et retourne une autre fonction.
multiplyBy(2) s'exécute une seule fois et te renvoie une toute nouvelle fonction. Cette nouvelle fonction se souvient encore de factor — c'est une closure, et on y consacrera une page entière plus tard. Pour l'instant, retiens ceci : en appelant multiplyBy avec différents arguments, tu obtiens autant de fonctions spécialisées construites à partir du même modèle.
Ce pattern, on le croise partout :
Une seule définition, deux fonctions réutilisables. Bien mieux que d'écrire warn et info à la main en devant garder les deux synchronisés.
Fonctions nommées vs callbacks en ligne
Tu peux passer une fonction fléchée directement en ligne, ou passer une fonction par son nom. Les deux marchent très bien — choisis ce qui se lit le mieux :
Quand tu passes isEven (sans parenthèses), tu transmets la fonction elle-même. Ajouter () l'appellerait aussitôt et ce serait le résultat qui serait passé — une erreur classique chez les débutants :
nums.filter(isEven); // correct : passe la fonction
nums.filter(isEven()); // incorrect : appelle isEven sans arguments, passe le résultat
Si le callback dépasse deux ou trois lignes, sors-le et donne-lui un nom. Le code autour gagne presque toujours en lisibilité.
Un exemple concret
Les fonctions d'ordre supérieur prennent tout leur sens quand on compose plusieurs petites briques. Imagine que tu as une liste de produits et que tu veux récupérer les noms des articles abordables et en stock, le tout en majuscules :
Chaque helper a un seul rôle. Chaque méthode de tableau effectue une seule transformation. Le pipeline se lit comme la spécification de ce que tu veux obtenir, et non comme la description de la façon de boucler.
Quand ne pas les utiliser
Les fonctions d'ordre supérieur, c'est super — mais ça ne remplace pas une boucle dans toutes les situations :
- Si tu dois t'arrêter en cours de route, un
forou unfor...ofavec unbreaksera plus clair que d'essayer de sortir d'unforEach. - Si tu fais de l'asynchrone dans le callback,
mapetforEachn'attendront pas. Utilise plutôtfor...ofavecawait, ouPromise.allcombiné àmap. - Si le callback modifie un état partagé, tu t'éloignes des points forts de ce style. Reviens à une boucle classique, ou refactore pour renvoyer de nouvelles valeurs.
Utilisées à bon escient, map, filter et reduce éliminent l'essentiel du code répétitif lié aux boucles dans le code du quotidien. Utilisées partout, elles finissent par nuire à la lisibilité. Choisis l'outil qui exprime l'intention le plus clairement.
La suite : les objets
Les fonctions ne sont pas les seules valeurs sur lesquelles construire. Les objets sont la véritable bête de somme de JavaScript pour regrouper données et comportements liés — et c'est précisément ce que contenaient la plupart des tableaux que tu viens de filtrer et de transformer. C'est le sujet de la page suivante.
Questions fréquentes
C'est quoi une fonction d'ordre supérieur en JavaScript ?
Une fonction d'ordre supérieur, c'est une fonction qui fait au moins l'une de ces deux choses : elle accepte une autre fonction en argument, ou elle renvoie une fonction comme résultat. Array.prototype.map, setTimeout ou encore addEventListener en sont des exemples classiques : on leur passe un callback et elles se chargent de l'exécuter pour nous.
Quelle différence entre map, filter et reduce ?
map transforme chaque élément et renvoie un nouveau tableau de la même taille. filter conserve uniquement les éléments pour lesquels le callback renvoie une valeur truthy — le tableau retourné peut donc être plus court. reduce agrège le tableau en une seule valeur, en combinant les éléments un à un. Les trois sont des fonctions d'ordre supérieur puisqu'elles attendent un callback.
Pourquoi renvoyer une fonction depuis une autre fonction ?
Pour créer des utilitaires configurables sans dupliquer la logique. Par exemple, multiplyBy(n) renvoie une nouvelle fonction qui multiplie par n : multiplyBy(2) et multiplyBy(10) te donnent ainsi deux fonctions spécialisées à partir d'une seule définition. Ce pattern repose sur les closures et on le croise partout : gestionnaires d'événements, middlewares, bibliothèques utilitaires…