Funzioni di ordine superiore in Javascript

Sto leggendo Eloquent JavaScript ( La nuova edizione ) e ho raggiunto la parte relativa alle funzioni di ordine superiore e sono confuso su ciò che sta accadendo nel seguente codice.

function noisy(f) { return function(arg) { console.log("calling with", arg); var val = f(arg); console.log("called with", arg, "- got", val); return val; }; } noisy(Boolean)(0); // → calling with 0 // → called with 0 - got false 
  1. Perché la chiamata alla funzione è così rumorosa? È (booleano) un cast? Un cast per cosa? il valore di ritorno? o l’argomento? perché no (booleano) rumoroso (0) se è il valore di ritorno. O rumoroso ((booleano) 0) se l’argomento è quello castato.

     noisy(Boolean)(0) 
  2. Cosa sta succedendo in questa linea? Dov’è definito f ()?

     var val = f(arg); 

  1. Boolean è una funzione. È la funzione che stai chiamando indirettamente attraverso il noisy . Un po ‘confuso, lo so, perché sembra il nome di un tipo. Ma in JavaScript, le cose inizialmente limitate ( Boolean , Number , String e così via) sono funzioni . Quando chiami Boolean ( senza usare new ), prova a convertire l’argomento che hai dato in un valore primitivo boolean e restituisce il risultato. (Vedi §15.6.1 nelle specifiche.)

  2. f è il nome dell’argomento nella funzione noisy .

Le funzioni in JavaScript sono oggetti di prima class. Puoi passarli in altre funzioni come argomenti proprio come qualsiasi altro object.

Quando lo fai

 noisy(Boolean)(0) 

Ci sono due cose in corso. Primo:

 // (In effect, we're not really creating a variable...) var x = noisy(Boolean); 

Questo ci dà una funzione che, quando chiamata, chiamerà Boolean con l’argomento che gli diamo mentre facciamo anche quelle istruzioni di console.log . Questa è la funzione che si vede creata in modo noisy ( return function(arg)... );

Quindi chiamiamo quella funzione:

 x(0); 

Ed è allora che vedi l’output della console. Dato che Boolean(0) è false , si vede che Boolean restituisce quel valore.

Ecco un esempio molto più semplice:

 function foo(bar) { bar(); } function testing() { alert("testing got called"); } foo(testing); 

Lì, sto passando la funzione testing in foo . Il nome dell’argomento che sto usando per quello dentro foo è bar . La bar(); linea bar(); chiama la funzione.

Una funzione senza () è la funzione effettiva. Una funzione con () è un’invocazione della funzione. Inoltre, tieni presente che JavaScript è un linguaggio generico, quindi non dichiarare i tipi di variabile. Ho aggiunto alcuni commenti al tuo esempio per provare e aiutare.

 // We define a function named noisy that takes in an argument named f. We are expecting f to be a function but this isn't enforced till the interpreter throws an error. function noisy(f) { // Noisy returns a single item, an anonymous function. That anonymous function takes in an argument named arg return function(arg) { console.log("calling with", arg); // Our anonymous function then takes f (It can use f because its defined inside noisy, see closures for more details) and invokes it with the argument arg and stores the result in a variable named val. var val = f(arg); console.log("called with", arg, "- got", val); // It now returns val return val; }; } 

Quindi, il rumore (booleano) (0) funziona così

f è la funzione Booleana

rumoroso restituisce una funzione come questa

 function(arg) { var val = Boolean(arg); return val; } 

Quindi ora abbiamo

la nostra funzione restituita (0)

che si esegue come normale per diventare

 function(0) { var val = Boolean(0); // false return val; } 

Sono relativamente nuovo a JS e ho anche appena letto tramite Eloquent Javascript e ho trovato più facile capire una volta capito il richiamo della funzione (rispondendo al punto 1):

 noisy(Boolean)(0); 

Il noisy(Boolean) crea una nuova funzione e il (0) lo segue perché viene passato come argomento in quella nuova funzione. Se rimandi al maggiore dell’esempio:

 function greaterThan(n) { return function(m) { return m > n; }; } var greaterThan10 = greaterThan(10); console.log(greaterThan10(11)); 

Potrebbe anche essere chiamato in questo modo:

 greaterThan(10)(11); 

Spero che chiarisca la tua prima domanda sul perché è stato chiamato così.

Per la seconda domanda. La f in:

 var val = f(arg); 

è la funzione Boolean passata in modo noisy quando è stato inserito il noisy(Boolean) . È stato quindi utilizzato come argomento nella funzione rumorosa. Inoltre non mi ero reso conto che Boolean poteva essere una funzione in sé e non solo un tipo di dati. Come altri hanno già detto, converte l’argomento che gli hai assegnato in un valore booleano e restituisce il risultato.

Pertanto val diventa Boolean(arg) che diventa Boolean(0) che restituisce false . Se provi a chiamare noisy(Boolean)(1); lo vedrai tornare true Il file console.log("called with", arg, "- got", val); registra semplicemente l’argomento (0 in questo caso) e il risultato della valutazione (falso).

In effetti, ha cambiato la funzione booleana in una che registra l’argomento e il risultato, oltre a restituire il risultato.

Spero che aiuti. Solo scriverlo ha aiutato la mia comprensione.

Nel caso tu stia ancora avendo problemi con questo, ecco come lo capisco (mi ha dato anche un mal di testa ..)

 function noisy(f) { return function(arg) { console.log("calling with", arg); var val = f(arg); console.log("called with", arg, "- got", val); return val; }; } noisy(Boolean)(0) 

Una funzione è solo un valore normale. La frase precedente è la chiave per capire cosa sta succedendo qui.

La nostra funzione rumorosa (f) è un valore. È ciò che restituisce.

rumoroso (f) restituisce una funzione che accetta un argomento (arg).

rumoroso (f) prende anche una discussione (f). Le funzioni interne (funzioni chiamate dall’interno delle funzioni) hanno accesso a variabili e argomenti passati alla funzione esterna.

Stiamo chiamando la nostra funzione esterna e passandoci l’argomento Boolean. La nostra funzione esterna restituisce la sua funzione interna che prende un argomento (0). Comprendendo quanto sopra dovrebbe essere chiaro che rumoroso (Booleano (0)) passerebbe semplicemente un argomento alla nostra funzione esterna, mentre non passerebbe nulla alla funzione interna che è restituita dalla nostra funzione esterna.

È così semplice davvero. Ora che lo comprendiamo, è difficile credere che ci abbia dato un tale mal di testa per cominciare con … * / `