Tutoriel JavaScript: fonctions d'ordre supérieur

La semaine dernière, j'ai laissé tomber le terme «fonction d'ordre supérieur» en parlant de mémorisation. Bien que je me sente à l'aise de lancer des termes comme ça maintenant, je ne savais pas toujours ce qu'ils signifiaient. Cette semaine, nous allons examiner ce que sont les fonctions d'ordre supérieur, montrer quelques exemples courants et apprendre comment créer les nôtres.

À la base, une fonction d'ordre supérieur est simplement une fonction qui accepte une fonction comme argument ou renvoie une fonction. Ceci est possible en JavaScript grâce à des fonctions de première classe, ce qui signifie que les fonctions en JavaScript peuvent être transmises comme n'importe quelle autre variable. Bien que cela semble assez simple, cela ne télégraphie pas tout à fait le type de puissance que vous avez avec des fonctions de première classe.

Si vous écrivez du JavaScript, vous avez probablement utilisé des fonctions d'ordre supérieur et vous n'avez même pas remarqué. Si vous avez déjà remplacé une forboucle par une méthode de tableau, vous avez utilisé des fonctions d'ordre supérieur. Si vous avez déjà utilisé les résultats d'un appel AJAX (sans async/ await), vous avez utilisé des fonctions d'ordre supérieur (les promesses et les rappels impliquent des fonctions d'ordre supérieur). Si vous avez déjà écrit un composant React qui affiche une liste d'éléments, vous avez utilisé des fonctions d'ordre supérieur. Voyons ces exemples:

éléments const = ['a', 'b', 'c', 'd', 'e']

// Au lieu de ça pour la boucle ....

pour (soit i = 0; i <items.length - 1; i ++) {

  console.log (éléments [i]);

}

// Nous pouvons utiliser forEach, une fonction d'ordre supérieur

// (forEach prend une fonction comme argument)

items.forEach ((item) => console.log (item));

// Rappels ou promesses, si vous faites

// requêtes asynchrones, vous utilisez

// fonctions d'ordre supérieur

get ('// aws.random.cat/meow', (réponse) => {

  putImageOnScreen (fichier de réponse);

});

get ('// random.dog/woof.json').then((response) => {

  putImageOnScreen (fichier de réponse);

});

// Dans le composant React ci-dessous, la carte est utilisée,

// qui est une fonction d'ordre supérieur

const myListComponent = (accessoires) => {

  revenir (

   

          {props.items.map ((élément) => {

            revenir (

  • {article}
  • )

          })}

      );

    };

Ce sont des exemples de fonctions d'ordre supérieur qui acceptent des fonctions comme arguments, mais beaucoup d'entre elles renvoient également des fonctions. Si vous avez déjà vu un appel de fonction comportant deux ensembles de parenthèses, c'est une fonction d'ordre supérieur. Ce genre de chose était moins courant, mais si vous travaillez avec Redux, vous avez probablement utilisé la connectfonction, qui est une fonction d'ordre supérieur:

exporter la connexion par défaut (mapStateToProps, mapDispatchToProps) (MyComponent);

Dans le cas ci-dessus, nous appelons connectavec deux arguments et il renvoie une fonction, que nous appelons immédiatement avec un argument. Vous avez peut-être également vu (ou écrit) une bibliothèque de journalisation simple qui utilise des fonctions comme valeurs de retour. Dans l'exemple ci-dessous, nous allons créer un enregistreur qui enregistre son contexte avant le message:

const createLogger = (contexte) => {

  retour (msg) => {

    console.log (`$ {contexte}: $ {msg}`);

  }

};

const log = createLogger ('monFichier');

log ('Un message très important');

// déconnecte "myFile: Un message très important"

L'exemple ci-dessus commence à illustrer une partie de la puissance des fonctions d'ordre supérieur (voir aussi mon article précédent sur la mémorisation). Notez que createLoggerprend un argument que nous référencons dans le corps de la fonction que nous retournons. Cette fonction renvoyée, que nous attribuons à la variable log, peut toujours accéder à l' contextargument car elle se trouvait dans la portée où la fonction a été définie.

Anecdote: le référencement contextest rendu possible par les fermetures. Je n'entrerai pas dans les fermetures ici car ils méritent leur propre message, mais ils peuvent être utilisés en conjonction avec des fonctions d'ordre supérieur pour des effets vraiment intéressants.

Par exemple, utiliser des fermetures avec des fonctions d'ordre supérieur était le seul moyen d'avoir des variables «privées» ou inviolables dans JavaScript:

let protectedObject = (fonction () {

  laissez myVar = 0;

  revenir {

    obtenir: () => maVar,

    incrément: () => maVar ++,

  };

}) ();

protectedObject.get (); // renvoie 0

protectedObject.increment ();

protectedObject.get (); // renvoie 1

myVar = 42; // oups! vous venez de créer une variable globale

protectedObject.get (); // renvoie toujours 1

Ne nous emportons pas, cependant. Les fonctions d'ordre supérieur ne nécessitent rien d'extraordinaire comme des fermetures. Ce sont simplement des fonctions qui prennent d'autres fonctions comme arguments ou qui renvoient des fonctions. Arrêt complet. Si vous voulez plus d'exemples ou des lectures supplémentaires, consultez le chapitre sur les fonctions d'ordre supérieur dans «Eloquent JavaScript» de Marijn Haverbeke.

Questions ou commentaires? N'hésitez pas à nous contacter sur Twitter: @freethejazz.