2016-03-29 47 views
5

Sto studiando da questo site ed è venuto su questa domanda e risposta:Come funziona il ritorno in Javascript senza che venga invocata una funzione?

Scrivete un metodo somma che funzionerà correttamente quando viene richiamato utilizzando seguente sintassi.

console.log(sum(2,3)); // Outputs 5 
console.log(sum(2)(3)); // Outputs 5 

// rispondere

function sum(x) { 
    if (arguments.length == 2) { 
    return arguments[0] + arguments[1]; 
    } else { 
    return function(y) { return x + y; }; 
    } 
} 

capisco il codice nella if, ma non nella dichiarazione altro, perché è semplicemente il ritorno di una funzione. Quella funzione non è chiamata con un '()', quindi dato il secondo scenario di console.log(sum(2)(3)); non vedo perché restituirà 5. Posso solo vedere che restituirà function(3) {return 2 + 3} che dovrebbe generare un errore.

+1

* "... Quella funzione non viene chiamata con un '()' ..." * Viene chiamata con '()'. Succede semplicemente di essere dopo il primo '()'. 'sum (2) (3)' Il '(2)' richiama 'sum', e' (3) 'invoca qualsiasi cosa sia stato restituito da' sum (2) '. –

risposta

2

L'istruzione else sta tornando una funzione con il valore x incapsulato dal primo invito

Per spiegarlo sarà scomposizione un po '

var fresult = sum(3); 

// right now fresult is a function that will add 3 
// to the variable you call fresult with 
// basically function(y){ return 3 + y; } 
var result = fresult(4); 

//result is 7 
console.log(result); 

Pensate a come il valore di x è essere catturato dalla funzione che viene restituito, che è quindi possibile chiamare

Questo incapsulamento viene creato dalla chiusura creato nella funzione anonima in dichiarazione di restituzione dell'altro

Per ulteriori informazioni sulle chiusure, dare un'occhiata a this MDN Article about them, sarà in grado di spiegarlo molto meglio di quanto avrei potuto.

in realtà hanno un esempio che è molto simile al tuo, dove cercano di spiegare il concetto come simile ad una fabbrica:

function makeAdder(x) { 
    return function(y) { 
    return x + y; 
    }; 
} 

var add5 = makeAdder(5); 
var add10 = makeAdder(10); 

console.log(add5(2)); // 7 
console.log(add10(2)); // 12 

articolo dice:

In questo esempio, abbiamo definito una funzione makeAdder (x) che prende un singolo argomento xe restituisce una nuova funzione. La funzione restituita accetta un singolo argomento y e restituisce la somma di x e y.

In pratica, makeAdder è una fabbrica di funzioni: crea funzioni che possono aggiungere un valore specifico al loro argomento. Nell'esempio sopra riportato usiamo la nostra factory di funzioni per creare due nuove funzioni - una che aggiunge 5 al suo argomento e una che aggiunge 10.

add5 e add10 sono entrambe le chiusure. Condivono la stessa definizione del corpo della funzione , ma memorizzano diversi ambienti. Nell'ambiente di ADD5, x è di 5. Per quanto riguarda l'Add10 è interessato, è x 10.

Così se siete abituati a un linguaggio di programmazione più tradizionale alcuni casi d'uso che si avrebbe per le variabili private sarebbe il come catturare valori di variabili in una chiusura

3
sum(2) = function (y){ return 2 + y } 

si sta chiamando che funzione con (3)

2

È possibile memorizzare una funzione in una variabile.

idea di base è

var foo = function(y) { 
    return y 
}; 

Così, quando guardiamo

console.log(sum(2)(3)); 

può essere scritta come

var part1 = sum(2); //aka part1 = function(y) { return 2 + y; }; 
var ans = part1(3); 
console.log(ans); 
1

else parte è una anonymous function che accetta one argomento.

In caso sum(2)(3)

Si va in loop di altro, dove x = 2 sin dalla sua chiamata come sum(2), mentre (3) è una funzione anonima senza nome.

quindi,

return function(y) { return x + y; }; 

diventa

return function(3) { return 2 + 3; }; 
1

Javascript è un po 'diverso da molte lingue. Le funzioni possono essere passate come variabili. Nel tuo caso, ciò che sta accadendo è molto più facile da vedere quando scomposto nei passaggi che si verificano effettivamente.

Innanzitutto, dal momento che sum(2) ha un solo parametro, passiamo al blocco else, che già conosci. Quello che sta accadendo è che stiamo restituendo una funzione, sostituendo x per la variabile che è stata passata a sum(x). Quindi, in sostanza, ciò che viene restituito è una funzione che restituisce 2 + y.Questo è quello che potrebbe apparire come se volevamo scriverlo da sola:

function(y) { 
    return 2 + y; 
} 

La seconda serie di parentesi nella sum(2)(3) è fondamentalmente dicendo "chiamare la funzione che è stato restituito dal sum(2) ed inviarlo il parametro 3 .

Ecco fondamentalmente una versione estesa di tutta l'operazione:

function sum(x) { 
    if (arguments.length == 2) { 
     return arguments[0] + arguments[1]; 
    } else { 
     return function(y) { return x + y; }; 
    } 
} 

var addTwo = sum(2); 

console.log(addTwo(3)); 

la versione breve fondamentalmente solo salta la creazione di una variabile separata per il risultato di un sum(2) d chiama immediatamente la nuova funzione.