Le but de closuresest simplement de préserver l' état; d'où le nom closure- il ferme sur l'état. Pour faciliter l'explication, j'utilise le langage Javascript.
Vous avez généralement une fonction
function sayHello(){
var txt="Hello";
return txt;
}
où la portée de la ou des variables est liée à cette fonction. Donc, après exécution, la variable txtsort de la portée. Il n'y a aucun moyen d'y accéder ou de l'utiliser une fois l'exécution de la fonction terminée.
Les fermetures sont des constructions de langage, qui permettent - comme dit précédemment - de conserver l’état des variables et donc de prolonger la portée.
Cela pourrait être utile dans différents cas. Un cas d'utilisation est la construction de fonctions d'ordre supérieur .
En mathématiques et en informatique, une fonction d'ordre supérieur (également forme fonctionnelle, fonctionnelle ou foncteur) est une fonction qui effectue au moins l'une des opérations suivantes: 1
- prend une ou plusieurs fonctions en entrée
- sort une fonction
Voici un exemple simple, mais pas trop utile:
makeadder=function(a){
return function(b){
return a+b;
}
}
add5=makeadder(5);
console.log(add5(10));
Vous définissez une fonction makedadderqui prend un paramètre en entrée et renvoie une fonction . Il existe une fonction externefunction(a){} et une fonction interne. En function(b){}{} outre, vous définissez (implicitement) une autre fonction add5à la suite de l'appel de la fonction d'ordre supérieur makeadder. makeadder(5)renvoie une fonction anonyme ( interne ), qui prend à son tour 1 paramètre et renvoie la somme du paramètre de la fonction externe et du paramètre de la fonction interne .
L' astuce est que, tout en renvoyant la fonction interne , qui effectue l'addition réelle, la portée du paramètre de la fonction externe ( a) est préservée. add5 se souvient que le paramètre aétait 5.
Ou pour montrer au moins un exemple 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"))));
Une autre utilisation courante est la dénommée IIFE = expression de fonction immédiatement appelée. Il est très fréquent en javascript pour faux variables membres privées. Cela se fait via une fonction, qui crée une portée privée = closure, car elle est immédiatement après la définition invoquée. La structure est function(){}(). Notez les crochets ()après la définition. Cela permet de l'utiliser pour la création d'objets avec un motif de module révélateur . L'astuce consiste à créer une étendue et à renvoyer un objet, qui a accès à cette étendue après l'exécution de l'IIFE.
L'exemple d'Addi ressemble à ceci:
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'objet retourné a des références à des fonctions (par exemple publicSetName), qui ont à leur tour accès à des variables "privées" privateVar.
Mais ce sont des cas d'utilisation plus spéciaux pour Javascript.
Quelle tâche spécifique un programmeur effectuerait-il et qui pourrait être mieux servi par une fermeture?
Il y a plusieurs raisons à cela. On pourrait dire que c'est naturel pour lui, puisqu'il suit un paradigme fonctionnel . Ou en Javascript: il est simplement nécessaire de s’appuyer sur les fermetures pour contourner certaines bizarreries du langage.