La fermeture est une difficulté dans la langue JavaScript et sa fonctionnalité. De nombreuses applications avancées s'appuient sur les fermetures à mettre en œuvre. Je suis exposé au concept de fermetures depuis longtemps, mais je suis confus et je n'ai pas été en mesure de comprendre ce que sont les fermetures JavaScript et ce qu'elles sont utiles. Aujourd'hui, j'ai vu un article sur les fermetures JavaScript (lien original) sur Internet. C'était très bien expliqué. Maintenant, j'ai complètement compris que les fermetures de JavaScript sont une chose magique et le but des fermetures. Je vais les écrire ici pour partager avec vous. J'espère que les amis qui ne comprennent pas les fermetures de JavaScript pourront comprendre les fermetures après les avoir lues! La plupart des contenus suivants proviennent du texte d'origine. J'ai ajouté des commentaires de code, des rendus d'opération et une petite modification au texte d'origine pour une compréhension facile!
1. La portée des variables
Pour comprendre les fermetures, vous devez d'abord comprendre la portée de la variable spéciale de JavaScript.
En JavaScript, la portée des variables est divisée en deux types: les variables globales et les variables locales.
Dans JavaScript, les variables globales peuvent être lues directement à l'intérieur d'une fonction.
var n =; // définir la variable globale nfonction f () {alert ("Accédez à la variable globale n, n =" + n); // accéder à la variable globale n} f (); //Résultats en cours:
Mais l'inverse n'est pas possible, les variables locales à l'intérieur de la fonction ne peuvent pas être lues en dehors de la fonction.
fonction f () {var n =; // définir la variable locale n} alert ("Accédez à la variable locale n en dehors de la fonction, n =" + n); // accéder à la variable locale n en dehors de la fonction, Erreur: n n'est pas définiRésultats en cours:
Il y a un endroit pour noter ici. Lors de la déclaration des variables en interne, vous devez utiliser la commande var. Sinon, c'est en fait une variable globale déclarée!
fonction f () {n =;} f (); alert ("n n'est pas déclaré avec var à l'intérieur de la fonction f1, à ce moment n est une variable globale, / r / n preuve: n =" + n + ", le résultat de window.n == n est:" + (window.n == n));Résultats en cours:
2. Comment lire les variables locales de l'extérieur?
Pour diverses raisons, nous devons parfois obtenir des variables locales dans la fonction. Cependant, comme mentionné précédemment, dans des circonstances normales, cela ne peut pas être fait et ne peut être réalisé que par des solutions de contournement.
C'est-à-dire définir une autre fonction à l'intérieur de la fonction.
fonction f () {var n =; // variable locale n à l'intérieur f fonction // définir une fonction de fonction f f () {// à l'intérieur f fonction, alert (n); //}}Dans le code ci-dessus, la fonction F2 est incluse à l'intérieur de la fonction F1, et toutes les variables locales à l'intérieur de F1 sont visibles par F2. Mais l'inverse n'est pas possible. Les variables locales à l'intérieur de F2 sont invisibles à F1. Il s'agit de la structure de la "chaîne de chaîne" unique à la langue javascript. Les objets enfants regarderont le niveau vers le haut par niveau pour toutes les variables d'objets parents. Par conséquent, toutes les variables de l'objet parent sont visibles par l'objet enfant, sinon ce n'est pas vrai. Puisque F2 peut lire les variables locales en F1, tant que F2 est utilisée comme valeur de retour, ne pouvons-nous pas lire ses variables internes en dehors de F1? Certaines personnes peuvent avoir des questions. F2 est une fonction, comment peut-elle être renvoyée comme la valeur de retour de la fonction F1? En fait, c'est OK. Le nom de la fonction dans JavaScript lui-même est une variable, donc la fonction peut également être utilisée comme variable normale. Autrement dit, non seulement une fonction peut être transmise à une autre fonction comme le passage des paramètres, mais une fonction peut également être renvoyée comme la valeur de retour d'une autre fonction.
fonction f () {var n =; // variable locale n // f fonction déclarée dans f fonction f () {alert (n); } return f; // Utiliser la fonction f comme la valeur de retour de la fonction f} var résultat = f (); // La valeur de retour après f est appelée est une fonction f, et le résultat est f fonction résultat (); // 999, appelez la fonction F2Résultats en cours:
3. Le concept de fermeture
La fonction F2 dans la section précédente du code est la fermeture. La définition de la «fermeture» dans divers documents professionnels est très abstraite. Par exemple, il existe une définition de fermeture: "Une fermeture JavaScript est une variable qu'il obtient de la fonction ou de la portée du niveau précédent dans une autre portée, et ces variables ne seront pas détruites à mesure que l'exécution de la fonction de niveau précédente est remplie." Il m'est difficile de comprendre une telle définition de fermeture. Ma compréhension est qu'une fermeture est une fonction qui peut lire les variables à l'intérieur d'autres fonctions. Étant donné que dans le langage JavaScript, seules les sous-fonctions à l'intérieur des fonctions peuvent lire les variables locales, les fermetures peuvent être simplement comprises comme "des fonctions définies à l'intérieur d'une fonction". Ainsi, en substance, une fermeture est un pont reliant l'intérieur et l'extérieur de la fonction.
4. Le but de la fermeture
Les fermetures peuvent être utilisées dans de nombreux endroits. Il a deux plus grandes utilisations, l'une est que les variables à l'intérieur de la fonction peuvent être lues comme mentionné ci-dessus, et l'autre est que les valeurs de ces variables sont toujours conservées en mémoire.
Comment comprendre cette phrase? Veuillez consulter le code ci-dessous.
Fonction f () {var n =; // NADD est une variable globale qui n'est pas déclarée en utilisant var. Cette variable pointe désormais vers une fonction anonyme déclarée à l'intérieur de la fonction f nadd = function () {n + =} function f () {alert (n); } return f; } var result = f (); // Le résultat est le résultat de la fonction f (); // le premier appel à la fonction de résultat nadd (); // nadd représente une fonction anonyme déclarée à l'intérieur de la fonction f, nadd () est le résultat de la fonction anonyme (); // le deuxième appel à la fonction de résultat 1000 1000Résultats en cours:
Dans ce code, le résultat est en fait la fonction F2 de fermeture. Il fonctionne deux fois au total, la première valeur est de 999 et la deuxième valeur est de 1000. Cela prouve que la variable locale n dans la fonction F1 a été maintenue en mémoire et n'est pas effacée automatiquement après l'appel F1.
Pourquoi cela se produit-il? La raison en est que F1 est la fonction parent de F2, et F2 est affecté à une variable globale, ce qui fait que F2 est toujours en mémoire, et l'existence de F2 dépend de F1. Par conséquent, F1 est toujours en mémoire et ne sera pas recyclé par le mécanisme de collecte des ordures une fois l'appel terminé.
Un autre point notable de ce code est que la ligne "nadd = function () {n + = 1}" est d'abord utilisée avant NADD, donc NADD est une variable globale, pas une variable locale. Deuxièmement, la valeur de NADD est une fonction anonyme, et cette fonction anonyme elle-même est également une fermeture, donc NADD est équivalent à un secteur, qui peut fonctionner sur des variables locales à l'intérieur de la fonction en dehors de la fonction.
5. Notes sur l'utilisation des fermetures
1) Étant donné que les fermetures entraîneront le stockage de toutes les variables de la fonction en mémoire et que la consommation de mémoire est très importante, les fermetures ne peuvent pas être abusées, sinon elle entraînera des problèmes de performances de la page Web et peut entraîner des fuites de mémoire dans IE. La solution consiste à supprimer toutes les variables locales qui ne sont pas utilisées avant de quitter la fonction.
2) La fermeture modifiera la valeur de la variable à l'intérieur de la fonction parent à l'extérieur de la fonction parent. Par conséquent, si vous utilisez la fonction parent comme un objet, utilisez la fermeture comme méthode publique et utilisez la variable interne comme propriété privée, veillez à ne pas modifier la valeur de la variable interne de la fonction parent à volonté.
6. Questions de réflexion
Si vous pouvez comprendre les résultats en cours d'exécution des deux éléments de code suivants, vous devez être considéré comme une compréhension du mécanisme de fonctionnement de la fermeture.
Extrait de code 1:
var name = "la fenêtre"; var objet = {name: "mon objet", getNameFunc: function () {return function () {return this.name; }; }}; alert (object.getNameFunc () () ());Résultats en cours:
Code Snippet deux:
var name = "la fenêtre"; var objet = {name: "mon objet", getNameFunc: function () {var that = this; return function () {return that.name; }; }}; alert (object.getNameFunc () ());Résultats en cours:
Les commentaires suivants sont ajoutés au code pour analyser les résultats en cours d'exécution des deux extraits de code ci-dessus:
Extrait de code 1:
L'analyse est la suivante:
/ * Dans JavaScript, les objets globaux JavaScript, les fonctions globales et les variables globales que nous déclarons deviendront automatiquement membres de l'objet Window. Les variables globales sont des propriétés des objets de fenêtre. Les fonctions globales sont des méthodes d'objets de fenêtre. * / var name = "la fenêtre"; // Déclare un nom de variable global, et à l'heure actuelle, le nom de variable global deviendra automatiquement un attribut de l'objet de la fenêtre // preuve: alert ("window.name:" + window.name); // Vous pouvez accéder au nom sous la forme de Window.Name (nom d'objet. Time l'objet de l'objet de variable global deviendra automatiquement un attribut de l'objet de fenêtre var objet = {name: "mon objet", // nom d'attribut de l'objet getNameFunc: function () {// objet getNameFunc de l'objet objet // La valeur de retour de la méthode GetNameFunc de l'objet est une fonction de la fenêtre anonyme qui s'appelle l'objet qui s'y trouve, et à ce moment à quel objet. // prouve que cela dans la fonction anonyme représente un objet de fenêtre au lieu d'un objectifalert ("Ce résultat de l'objet == est:" + (this == objet)); alert ("ce résultat de la fenêtre == est:" + (cette fenêtre ==)); retourne this.name; // puisque cela représente un objet de fenêtre, alors ce nom accède naturellement au nom de l'objet de fenêtre "la fenêtre"}; }}? À l'heure actuelle, RETFN représente une méthode anonyme. Maintenant, il équivaut à donner à la méthode anonyme un nom retfn. À l'heure actuelle, la fonction RETFN devient automatiquement une fonction de l'objet Window * / var retfn = object.getNameFunc (); alert (retfn ()); // appelant la méthode anonyme renvoyée, alors qui appelle cette méthode anonyme? Il s'agit d'un objet de fenêtre // preuve: la fonction retfn est une fonction de l'alerte de l'objet de fenêtre ("window.retfn ():" + window.retfn ()); // Vous pouvez appeler la méthode RETFN sous la forme de Window.Retfn () (nom de la méthode.Code Snippet deux:
L'analyse est la suivante:
var name = "la fenêtre"; // Nom de la variable globale // objet global objet objetvar objet = {name: "mon objet", getNameFunc: function () {/ * Quel objet cela représente-t-il cela en ce moment? Cela représente l'objet objet. Quel objet appelle la fonction où cela se trouve? Cela fait référence à quel objet a été exécuté que = ceci, et cela représente également l'objet objet * / var que = this; // c'est une variable locale déclarée dans la fonction getNameFunc // prouve que cela dans la fonction getNameFunc représente l'objet objet au lieu de windowalert ("Ce résultat == Objet est:" + (this == objet)); alert ("ce résultat de la fenêtre == est:" + (this == fenêtre)); // prouve que représente l'alerte d'objet objet ("ce résultat == objet est:" + (that == objet)); return function () {/ * c'est une variable locale déclarée dans la fonction getNameFunc. Dans des circonstances normales, une fois l'appel de fonction GetNameFunc terminé, la variable locale qui sera recyclée par le GC de JavaScript, libérant l'espace mémoire occupé par la variable locale qui, mais maintenant, cela peut être utilisé normalement et n'a pas été recyclé. La raison en est que GetNameFunc est la fonction parentale de la fonction anonyme. Une fois que la fonction GetNameFunc est appelée, la fonction anonyme sera renvoyée et attribuée à une variable globale RETFN, ce qui fait que la fonction anonyme est toujours en mémoire, et l'existence de la fonction anonyme dépend de la fonction getNameFunc. Par conséquent, la fonction GetNameFunc est toujours en mémoire et ne sera pas recyclée par le mécanisme de collecte des ordures une fois l'appel terminé. Étant donné que la fonction getNameFunc est toujours en mémoire, la variable locale déclarée à l'intérieur de la fonction getNameFunc existera toujours en mémoire. Puisqu'il existe, bien sûr, il peut continuer à être utilisé. *! }}; var retfn = object.getNamefunc (); // Après avoir appelé la méthode getNameFunc, une méthode anonyme est renvoyée. À l'heure actuelle, RETFN représente une méthode anonyme, qui équivaut désormais à donner à la méthode anonyme qu'un nom est RetFn Alert (retfn ());Enfin, j'ai également joint un exemple que j'ai écrit lorsque j'ai déjà appris les fermetures JavaScript:
<script type = "text / javascript"> function a () {var i =; // Déclare la variable locale i à l'intérieur de la fonction a / Déclare la sous-fonction bfonction b () {alert ("i =" + (++ i)); // accéder à la variable locale i a déclaré à l'intérieur de la fonction a au sein de la fonction a} return b; // return C. à la fonction b. né La variable i est utilisée. Après avoir exécuté c (), une fenêtre apparaîtra pour afficher la valeur de i (la première fois) et ce code crée en fait une fermeture, car la variable C en dehors de la fonction A fait référence à la fonction B à l'intérieur de la fonction a. C'est-à-dire: Lorsque la fonction interne B de la fonction a est référencée par une variable extérieure a fonction a, une fermeture dite "fermeture" est créée. Une fois qu'un a été exécuté et retourné, la fermeture fait que le mécanisme de collecte des ordures JavaScript GC ne recyclera pas les ressources occupées par A, car l'exécution de la fonction interne B d'un a besoin de s'appuyer sur la variable dans un * / a (); // il y aura certainement de l'espace en mémoire. Une fois un () exécuté, GC recyclera l'espace mémoire alloué pour i var c = a (); // cette utilisation, GC ne traitera pas i comme des ordures et c (); // équivalent à l'appel b (), le résultat est: i = c (); // le résultat est: i = c (); // le résultat est: i = c (); // le résultat est: i = </ script>Résultats en cours:
Le contenu ci-dessus est l'explication détaillée du code de fermeture JavaScript (fermeture) des points de connaissance JavaScript résumés (16) introduits par l'éditeur. J'espère que ce sera utile à tous!