Tutorial JavaScript: funzioni di ordine superiore

La scorsa settimana, ho casualmente abbandonato il termine "funzione di ordine superiore" quando parlo di memoizzazione. Anche se ora mi sento a mio agio a lanciare termini del genere, non ho sempre saputo cosa significassero. Questa settimana esamineremo cosa sono le funzioni di ordine superiore, mostreremo alcuni esempi comuni e impareremo come creare le nostre.

Fondamentalmente, una funzione di ordine superiore è solo una funzione che accetta una funzione come argomento o restituisce una funzione. Questo è possibile in JavaScript grazie a funzioni di prima classe, il che significa che le funzioni in JavaScript possono essere passate come qualsiasi altra variabile. Anche se questo sembra abbastanza semplice, non telegrafa abbastanza il tipo di potere che hai con le funzioni di prima classe.

Se scrivi JavaScript, probabilmente hai utilizzato funzioni di ordine superiore e non te ne sei nemmeno accorto. Se hai mai sostituito un forciclo con un metodo array, hai utilizzato funzioni di ordine superiore. Se hai mai utilizzato i risultati di una chiamata AJAX (senza async/ await), hai utilizzato funzioni di ordine superiore (sia le promesse che i callback coinvolgono funzioni di ordine superiore). Se hai mai scritto un componente React che mostra un elenco di elementi, hai utilizzato funzioni di ordine superiore. Vediamo quegli esempi:

elementi cost = ["a", "b", "c", "d", "e"]

// Invece di questo ciclo for ....

for (let i = 0; i <items.length - 1; i ++) {

  console.log (elementi [i]);

}

// Possiamo usare forEach, una funzione di ordine superiore

// (forEach accetta una funzione come argomento)

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

// Richiami o promesse, se lo stai facendo

// richieste asincrone, stai usando

// funzioni di ordine superiore

get ('// aws.random.cat/meow', (response) => {

  putImageOnScreen (response.file);

});

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

  putImageOnScreen (response.file);

});

// Nel componente React di seguito, viene utilizzata map,

// che è una funzione di ordine superiore

const myListComponent = (props) => {

  ritorno (

   

          {props.items.map ((item) => {

            ritorno (

  • {articolo}
  • )

          })}

      );

    };

Questi sono esempi di funzioni di ordine superiore che accettano funzioni come argomenti, ma molte di esse restituiscono anche funzioni. Se hai mai visto una chiamata di funzione che ha due serie di parentesi, questa è una funzione di ordine superiore. Questo genere di cose era meno comune, ma se lavori con Redux, probabilmente hai usato la connectfunzione, che è una funzione di ordine superiore:

export default connect (mapStateToProps, mapDispatchToProps) (MyComponent);

Nel caso precedente, chiamiamo connectcon due argomenti e restituisce una funzione, che chiamiamo immediatamente con un argomento. Potresti anche aver visto (o scritto) una semplice libreria di registrazione che utilizza le funzioni come valori di ritorno. Nell'esempio seguente, creeremo un logger che registra il suo contesto prima del messaggio:

const createLogger = (contesto) => {

  return (msg) => {

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

  }

};

const log = createLogger ('myFile');

log ("Un messaggio molto importante");

// disconnette "myFile: un messaggio molto importante"

L'esempio sopra inizia a illustrare alcune delle potenzialità delle funzioni di ordine superiore (vedi anche il mio post precedente sulla memoizzazione). Nota che createLoggeraccetta un argomento a cui facciamo riferimento nel corpo della funzione che restituiamo. Quella funzione restituita, che assegniamo alla variabile log, può ancora accedere contextall'argomento perché era nell'ambito in cui la funzione è stata definita.

Curiosità: la referenziazione contextè resa possibile dalle chiusure. Non entrerò nelle chiusure qui perché meritano il loro post, ma possono essere utilizzate insieme a funzioni di ordine superiore per alcuni effetti davvero interessanti.

Ad esempio, l'uso di chiusure insieme a funzioni di ordine superiore era l'unico modo in cui potevamo avere variabili "private" oa prova di manomissione in JavaScript:

let protectedObject = (function () {

  let myVar = 0;

  ritorno {

    get: () => myVar,

    incremento: () => myVar ++,

  };

}) ();

protectedObject.get (); // restituisce 0

protectedObject.increment ();

protectedObject.get (); // restituisce 1

myVar = 42; // whoops! hai appena creato una variabile globale

protectedObject.get (); // restituisce ancora 1

Non lasciamoci trasportare, però. Le funzioni di ordine superiore non richiedono nulla di speciale come le chiusure. Sono semplicemente funzioni che accettano altre funzioni come argomenti o che restituiscono funzioni. Punto. Se vuoi altri esempi o ulteriori letture, controlla il capitolo sulle funzioni di ordine superiore in "Eloquent JavaScript" di Marijn Haverbeke.

Domande o commenti? Sentiti libero di metterti in contatto con Twitter: @freethejazz.