Lo scopo di closures
è semplicemente quello di preserve ; da qui il nome closure
- esso chiude su stato.
Per la facilità di ulteriori spiegazioni, userò Javascript.
In genere hai una funzione
function sayHello(){
var txt="Hello";
return txt;
}
dove l'ambito della variabile (o delle variabili) è associato a questa funzione. Quindi dopo l'esecuzione la variabile txt
esce dall'ambito. Non c'è modo di accedervi o utilizzarlo dopo che la funzione ha terminato l'esecuzione.
Le chiusure sono costrutti linguistici, che consentono - come detto prima - di preservare lo stato delle variabili e quindi prolungare l'ambito.
Questo potrebbe essere utile in diversi casi. Un caso d'uso è la costruzione di funzioni di ordine superiore .
In mathematics and computer science, a higher-order function (also functional form, functional or functor) is a function that does at least one of the following:1
- takes one or more functions as an input
- outputs a function
Un esempio semplice, ma non del tutto utile è:
makeadder=function(a){
return function(b){
return a+b;
}
}
add5=makeadder(5);
console.log(add5(10));
Definisci una funzione makedadder
, che accetta un parametro come input e restituisce una funzione . Esiste una funzione esterna function(a){}
e una interna function(b){}{}
. Inoltre, definisci (implicitamente) un'altra funzione add5
come risultato della chiamata della funzione di ordine superiore% codice%. makeadder
restituisce una funzione anonima ( interiore ), che a sua volta assume 1 parametro e restituisce la somma del parametro della funzione esterna e il parametro di inner .
Il trucco è che, mentre si restituisce la funzione interiore , che fa l'aggiunta effettiva, l'ambito del parametro della funzione esterna ( makeadder(5)
) è conservato . a
ricorda , che il parametro add5
era a
.
O per mostrarne uno almeno in qualche modo utile:
makeTag=function(openTag, closeTag){
return function(content){
return openTag +content +closeTag;
}
}
table=makeTag("<table>","</table>")
tr=makeTag("<tr>", "</tr>");
td=makeTag("<td>","</td>");
console.log(table(tr(td("I am a Row"))));
Un altro usecase comune è il cosiddetto IIFE = espressione della funzione immediatamente invocata.
È molto comune in javascript alle false variabili dei membri privati. Questo viene fatto tramite una funzione, che crea un private scope = 5
, perché è immediatamente dopo la definizione richiamata. La struttura è closure
. Notare le parentesi function(){}()
dopo la definizione.
Ciò rende possibile utilizzarlo per la creazione di oggetti con modello di modulo rivelatore .
Il trucco sta nel creare un ambito e restituire un oggetto, che ha accesso a questo ambito dopo l'esecuzione dell'IFE.
L'esempio di Addi ha questo aspetto:
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
L'oggetto restituito ha riferimenti a funzioni (ad esempio ()
), che a loro volta hanno accesso alle variabili "private" publicSetName
.
Ma questi sono casi d'uso più speciali per Javascript.
What specific task would a programmer be performing that might be best served by a closure?
Ci sono diversi motivi per questo. Uno potrebbe essere, che è naturale per lui, dal momento che segue un paradigma funzionale . O in Javascript: è semplicemente necessario fare affidamento sulle chiusure per eludere alcuni aspetti della lingua.