Préface: c'est toujours un article d'introduction. Il existe plusieurs fonctionnalités linguistiques très importantes dans JavaScript - objets, héritage du prototype et fermetures. Parmi eux, les fermetures sont une nouvelle fonctionnalité linguistique pour les programmeurs qui utilisent le langage statique traditionnel C / C ++. Cet article commencera par des exemples pour présenter les fonctionnalités linguistiques des fermetures JavaScript et combiner quelques spécifications de langage ECMAScript pour permettre aux lecteurs de comprendre plus profondément les fermetures.
Remarque: Cet article est un article d'introduction, et l'exemple de matériel est compilé sur Internet. Si vous êtes un maître, vous êtes invités à présenter des suggestions et des opinions techniques sur l'article. Cet article traite de JavaScript et vous ne voulez pas comparer les langues. Si vous êtes naturellement inconfortable avec JavaScript, veuillez prendre un détour.
Qu'est-ce qu'une fermeture
Qu'est-ce qu'une fermeture? La fermeture est la fermeture, qui est une nouvelle fonctionnalité que les langues statiques n'ont pas. Mais les fermetures ne sont pas quelque chose de si compliqué qu'ils sont incompréhensibles. En bref, les fermetures sont:
Les fermetures sont l'ensemble des variables locales de la fonction, mais ces variables locales continueront d'exister après le retour de la fonction.
Les fermetures sont la "pile" de la fonction et ne sont pas libérées après le retour de la fonction. Nous pouvons également comprendre que ces piles de fonction ne sont pas allouées sur la pile mais sont allouées sur le tas.
Lors de la définition d'une autre fonction dans une fonction, une fermeture sera générée
La deuxième définition ci-dessus est la première description supplémentaire, qui extrait l'objet de prédicate de sujet de la première définition - la fermeture est un ensemble de fonctions «variable locale». C'est juste que cette variable locale est accessible après le retour de la fonction. (Ce n'est pas une définition officielle, mais cette définition devrait être plus propice à votre compréhension des fermetures)
En tant que variables locales, ils sont accessibles par le code de la fonction, et il n'y a pas de différence entre ce langage statique. La différence entre les fermetures est que les variables locales sont toujours accessibles par code en dehors de la fonction après l'exécution de la fonction. Cela signifie que la fonction doit renvoyer une "référence" à la fermeture, ou attribuer cette "référence" à une variable externe pour s'assurer que les variables locales de la fermeture sont accessibles par code externe. Bien sûr, l'entité contenant cette référence doit être un objet, car en JavaScript, tous les autres, sauf que les types de base sont des objets. Malheureusement, ECMAScript ne fournit pas de membres et de méthodes pertinents pour accéder aux variables locales dans la fermeture. Cependant, dans ECMAScript, la fonction interne définie dans l'objet de fonction est une variable locale qui peut accéder directement aux fonctions externes. Grâce à ce mécanisme, nous pouvons terminer l'accès à la fermeture de la manière suivante.
La copie de code est la suivante:
Fonction Greeting (Name) {
var text = 'hello' + name; // Variable locale
// Chaque fois qu'une fermeture est générée et l'objet de fonction interne est renvoyé à l'appelant
return function () {alert (text); }
}
var sayshello = salutation ("fermeture");
sayshello () // accéder au texte variable local à travers la fermeture
Le résultat d'exécution du code ci-dessus est: Hello Closeure, car une fois la fonction de salutation exécutée, la fonction SayHello () peut toujours accéder au texte de variable local défini à l'intérieur.
Ok, c'est l'effet de la fermeture légendaire. Les fermetures ont de nombreux scénarios et modes d'application dans JavaScript, tels que Singleton, Power Constructor et d'autres modes JavaScript qui sont inséparables à partir de l'utilisation des fermetures.
Modèle de fermeture ECMAScript
Comment ECMAScript implémente-t-il les fermetures? Si vous souhaitez avoir une compréhension approfondie, vous pouvez obtenir les spécifications ECMAScript pour la recherche. Je ne donnerai qu'une explication simple ici, et le contenu provient également d'Internet.
Lorsque la fonction du script ECMAScript s'exécute, chaque association de fonction a un scénario de contexte d'exécution (contexte d'exécution), qui contient trois parties.
La lexicévironment
La variable-environnement
Cette reliure
Le troisième point de cette contrainte n'a rien à voir avec les fermetures et n'est pas discuté dans cet article. Un identifiant variable utilisé dans l'environnement grammatical pour analyser le processus d'exécution de la fonction. Nous pouvons considérer un environnement grammatical comme un objet qui contient deux composants importants, l'environnement d'environnement (Enviroment Recode) et une référence externe (pointeur). L'enregistrement d'environnement contient des variables locales et des variables de paramètres déclarées en interne par la fonction, et la référence externe pointe vers le scénario d'exécution de contexte de l'objet de fonction externe. Cette valeur de référence est nul dans le scénario de contexte global. Une telle structure de données constitue une liste liée à sens unique, chaque référence pointe vers le scénario de contexte extérieur.
Par exemple, le modèle de fermeture dans notre exemple ci-dessus devrait être comme ça. La fonction Sayhello est au niveau le plus bas, le niveau supérieur est la salutation de la fonction et le niveau le plus extérieur est la scène globale. Comme le montre la figure ci-dessous: Par conséquent, lorsque Sayshello est appelé, Sayshello trouvera la valeur du texte variable local à travers la scène du contexte, de sorte que l'environnement variable "Hello Close" (l'environnement variable) et l'environnement de grammaire sont essentiellement les mêmes. Pour des différences spécifiques, veuillez vous référer au document de spécification ECMAScript.
Exemple de colonne de fermetures
Dans l'article précédent, je comprends grossièrement ce qu'est la fermeture JavaScript et comment les fermetures sont implémentées dans JavaScript. Ci-dessous, nous vous aiderons à comprendre plus profondément les fermetures en ciblant quelques exemples. Il y a 5 exemples ci-dessous, et les exemples proviennent de fermetures JavaScript pour les nuls (miroir). Exemple 1: Les variables locales dans les fermetures sont des références plutôt que des copies
La copie de code est la suivante:
fonction dit667 () {
// Variable locale qui finit par la fermeture
var num = 666;
var saysalert = function () {alert (num); }
num ++;
Retour SaidAlert;
}
var saidAlert = say667 ();
SayAlert ()
Par conséquent, le résultat d'exécution devrait apparaître 667 au lieu de 666.
Exemple 2: Plusieurs fonctions lient la même fermeture car elles sont définies dans la même fonction.
La copie de code est la suivante:
Configuration de fonctionsomeGlobal () {
// Variable locale qui finit par la fermeture
var num = 666;
// Stockez quelques références aux fonctions comme des variables globales
galertNumber = function () {alert (num); }
ginCreasenumber = function () {num ++; }
gsetNumber = fonction (x) {num = x; }
}
ConfigurationSomeGlobal (); // attribue des valeurs à trois variables globales
GalertNumber (); // 666
ginCreasenumber ();
GalertNumber (); // 667
gsetNumber (12); //
galertNumber (); // 12
Exemple 3: Lors de l'attribution de fonctions dans une boucle, ces fonctions lieront la même fermeture
La copie de code est la suivante:
fonction buildList (list) {
var result = [];
pour (var i = 0; i <list.length; i ++) {
var item = 'item' + list [i];
result.push (function () {alert (item + '' + list [i])});
}
Résultat de retour;
}
fonction testList () {
var fnlist = buildList ([1,2,3]);
// Utilisation de J uniquement pour aider à prévenir la confusion - pourrait utiliser i
pour (var j = 0; j <fnlist.length; j ++) {
fnlist [j] ();
}
}
Le résultat de l'exécution de Testlist est que la fenêtre non définie de l'élément3 apparaît trois fois, car ces trois fonctions lient la même fermeture, et la valeur de l'élément est le dernier résultat calculé, mais lorsque je saute de la boucle, la valeur I est 4, donc le résultat de la liste [4] n'est pas défini.
Exemple 4: Toutes les variables locales de fonctions externes sont dans la fermeture, même si cette variable est déclarée après la définition de la fonction interne.
La copie de code est la suivante:
fonction sdedalice () {
var saidAlert = function () {alert (Alice); }
// Variable locale qui finit par la fermeture
var Alice = 'Hello Alice';
Retour SaidAlert;
}
var helloalice = sayalice ();
helloalice ();
Le résultat de l'exécution est une fenêtre avec une fenêtre contextuelle "Hello Alice". Même si la variable locale déclare après la fonction SADELERT, la variable locale est toujours accessible.
Exemple 5: Créez une nouvelle fermeture à chaque fois que la fonction est appelée
La copie de code est la suivante:
fonction newclosure (Somenum, Someref) {
// Variables locales qui finissent dans la fermeture
var num = Somenum;
var anArray = [1,2,3];
var ref = Someref;
return function (x) {
num + = x;
anArray.push (num);
alert ('num:' + num +
'/ nanarray' + anarray.tostring () +
'/nref.somevar' + ref.somevar);
}
}
Closure1 = newClosure (40, {SomeVar: 'Close 1'});
clôture2 = newClosure (1000, {SomeVar: 'Close 2'});
fermeture1 (5); // num: 45 anarray [1,2,3,45] Réf: «Somevar Close1»
Close2 (-10); // num: 990 Anarray [1,2,3,990] Réf: «SomeVar Close2»
Application des fermetures
Singleton Single Piece:
La copie de code est la suivante:
var singleton = function () {
var privatevariable;
fonction privatefunction (x) {
... privatevariable ...
}
retour {
FirstMethod: fonction (a, b) {
... privatevariable ...
},
SecondMethod: fonction (c) {
... PrivateFunction () ...
}
};
} ();
Cette pièce unique est réalisée grâce à une fermeture. L'encapsulation des membres privés et des méthodes est terminée par les fermetures. La fonction principale anonyme renvoie un objet. L'objet contient deux méthodes, la méthode 1 peut utiliser des variables privées et la méthode 2 peut accéder aux fonctions privées internes. La chose à noter est le «()» où la fonction principale anonyme se termine. Sans cela '()', une seule pièce ne peut pas être produite. Parce que les fonctions anonymes ne peuvent renvoyer que des objets uniques et ne peuvent pas être appelés ailleurs. Il s'agit de la méthode d'utilisation des fermetures pour générer des pièces simples.