var foo = "hello"; var c = (function a () {function b () {var bar = "world"; alert (foo + bar); retour bar;} return b;}) () (); alert (foo + c);Cet exemple apparaît Hello World deux fois;
1. Qu'est-ce qu'une fermeture?
L'explication "officielle" est: la soi-disant "fermeture" fait référence à une expression (généralement une fonction) qui a de nombreuses variables et un environnement lié à ces variables, de sorte que ces variables font également partie de l'expression.
Je crois que peu de gens peuvent comprendre directement cette phrase parce qu'il l'a décrit trop académiquement. Je veux utiliser comment créer une fermeture en JavaScript pour vous dire ce qu'est une fermeture, car il est très difficile de comprendre directement la définition d'une fermeture en sautant le processus de création de fermeture. Regardez le code suivant:
fonction a () {var i = 0; fonction b () {alert (++ i);} return b;} var c = a (); c ();Ce code a deux caractéristiques:
1. La fonction B est imbriquée à l'intérieur de la fonction a;
2. Fonction A Renvoie la fonction b.
De cette façon, après avoir exécuté var c = a (), la variable c pointe en fait la fonction b. Après avoir exécuté c (), une fenêtre apparaîtra pour afficher la valeur de I (la première fois est 1). Ce code crée en fait une fermeture. Pourquoi? Parce que la fonction extérieure C variable 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 de fonction a, une fermeture est créée.
Je suppose que vous ne comprenez toujours pas les fermetures parce que vous ne savez pas ce que les fermetures ont. Continuons à explorer ci-dessous.
2. Quelle est la fonction des fermetures?
En bref, la fonction d'une fermeture est qu'après que A a été exécuté et retourné, la fermeture fait que le mécanisme de collecte des ordures JavaScript n'a pas récupéré les ressources occupées par A, car l'exécution d'une fonction interne b de A doit s'appuyer sur les variables en a. Il s'agit d'une description très simple du rôle des fermetures, qui n'est ni professionnel ni rigoureuse, mais cela signifie à peu près que c'est le cas. Comprendre les fermetures nécessite un processus progressif.
Dans l'exemple ci-dessus, une fois la fonction a renvoyée, je existe toujours, donc chaque fois que c () est exécuté, je suis la valeur de i alerté après l'ajout de 1.
Alors imaginons une autre situation. Si un renvoie pas la fonction B, la situation est complètement différente. Parce qu'après avoir exécuté A, B n'est pas renvoyé dans le monde extérieur de A, mais n'est référencé que par A, et à l'heure actuelle, A ne sera référencé que par B, donc les fonctions A et B sont référencées les unes aux autres mais ne seront pas perturbées par le monde extérieur (référé par le monde extérieur), les fonctions A et B seront recyclées par GC. (Le mécanisme de collecte des ordures de JavaScript sera introduit en détail plus tard)
3. Le monde microscopique de la fermeture
Si nous voulons avoir une compréhension plus approfondie de la relation entre les fermetures et la fonction A et la fonction imbriquée B, nous devons introduire plusieurs autres concepts: l'environnement d'exécution de la fonction (contexte d'excuse), l'objet actif (objet d'appel), la portée (portée) et la chaîne de portée. Prenez le processus de fonction A de la définition à l'exécution comme exemple pour illustrer ces concepts.
1. Lors de la définition de la fonction A, l'interprète JS définira la chaîne de portée de la fonction A à «l'environnement» où A est situé lors de la définition a. Si A est une fonction globale, il n'y a que des objets de fenêtre dans la chaîne de portée.
2. Lorsque la fonction a est exécutée, A entrera dans l'environnement d'exécution correspondant (contexte d'excuse).
3. Dans le processus de création d'un environnement d'exécution, A ajoutera d'abord un attribut de portée, c'est-à-dire la portée de A, et sa valeur est la chaîne de portée à l'étape 1. C'est-à-dire la chaîne de portée de A.Scope = a.
4. L'environnement d'exécution créera alors un objet actif (objet d'appel). L'objet actif est également un objet avec des attributs, mais il n'a pas de prototype et ne peut pas être directement accessible via le code JavaScript. Après avoir créé l'objet actif, ajoutez l'objet actif au sommet de la chaîne de portée de a. À l'heure actuelle, la chaîne de portée de A contient deux objets: l'objet actif de A et l'objet Window.
5. L'étape suivante consiste à ajouter un attribut d'arguments à l'objet actif, qui enregistre les paramètres passés lors de la fonction d'appel a.
6. Enfin, ajoutez tous les paramètres formels de la fonction A et les références à la fonction interne B à l'objet actif de A. À cette étape, la définition de la fonction B est terminée, de sorte que à l'étape 3, la chaîne de portée de la fonction B est définie sur l'environnement défini par B, c'est-à-dire la portée de A.
À ce stade, la fonction entière A est terminée de la définition à l'exécution. À l'heure actuelle, A renvoie une référence à la fonction B à C, et la chaîne de portée de la fonction B contient une référence à l'objet actif de la fonction A, c'est-à-dire que B peut accéder à toutes les variables et fonctions définies dans a. La fonction B est référencée par C, et la fonction B s'appuie sur la fonction A, donc la fonction A ne sera pas recyclée par GC après son retour.
Lorsque la fonction B est exécutée, ce sera également le même que ci-dessus. Par conséquent, la chaîne de portée de B pendant l'exécution contient 3 objets: l'objet actif de B, l'objet actif de A et l'objet de fenêtre, comme indiqué sur la figure ci-dessous:
Comme le montre la figure, lors de l'accès à une variable dans la fonction B, l'ordre de recherche est de rechercher d'abord son propre objet actif, et s'il existe, il reviendra. S'il n'existe pas, il continuera à rechercher l'objet actif de la fonction A et à rechercher à son tour jusqu'à ce qu'il soit trouvé. S'il ne peut être trouvé sur toute la chaîne de portée, un non-défini est retourné. S'il existe un prototype d'objet prototype pour la fonction B, puis après avoir recherché son propre objet actif, recherchez d'abord son propre objet prototype, puis continuez à rechercher. Il s'agit du mécanisme de recherche variable en JavaScript.
4. Scénarios d'application des fermetures
1. Protégez la sécurité des variables dans la fonction. Prenant le premier exemple à titre d'exemple, dans la fonction A, je ne peux être accessible que par la fonction B, mais ne peut pas être accessible via d'autres canaux, protégeant ainsi la sécurité de i.
2. Maintenez une variable en mémoire. Toujours comme auparavant, en raison de la fermeture, je suis en fonction A toujours en mémoire, donc chaque fois que C () est exécuté, je serai ajouté 1.
Les deux points ci-dessus sont les scénarios d'application les plus élémentaires pour les fermetures, et de nombreux cas classiques en découlent.
5. Mécanisme de collecte des ordures de Javascript
Dans JavaScript, si un objet n'est plus référencé, l'objet sera recyclé par GC. Si deux objets sont référencés l'un à l'autre et ne sont plus référencés par la troisième personne, les deux objets référencés l'un à l'autre seront recyclés. Parce que la fonction A est référencée par B, B est référencée par C en dehors de A, c'est pourquoi la fonction A ne sera pas recyclée après l'exécution.
L'article ci-dessus comprend complètement que le mécanisme de fermeture est tout le contenu que je partage avec vous. J'espère que vous pourrez vous faire référence et j'espère que vous pourrez soutenir Wulin.com plus.