Maison >interface Web >js tutoriel >Compréhension approfondie des fermetures js et de leurs fonctions
Le contenu de cet article est de partager avec vous une compréhension approfondie des fermetures js et de leurs fonctions. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer
Ce code a deux caractéristiques :1. La fonction b est imbriquée dans la fonction a
2.
La relation de référence est celle indiquée sur la figure :
Lorsque la fonction b à l'intérieur de la fonction a est référencée par une variable à l'extérieur de la fonction a, une fermeture est créée. Soyons plus minutieux. Ce qu'on appelle la « fermeture » consiste à définir une autre fonction dans le corps du constructeur comme fonction de méthode de l'objet cible, et la fonction de méthode de cet objet fait à son tour référence à la variable temporaire dans le corps de fonction externe. Cela permet de conserver indirectement les valeurs des variables temporaires utilisées par le corps du constructeur d'origine tant que l'objet cible peut toujours conserver ses méthodes pendant sa durée de vie. Bien que l'appel initial du constructeur soit terminé et que le nom de la variable temporaire ait disparu, la valeur de la variable peut toujours être référencée dans la méthode de l'objet cible et la valeur n'est accessible que via cette méthode. Même si le même constructeur est appelé à nouveau, seuls de nouveaux objets et méthodes seront générés, et les nouvelles variables temporaires ne correspondent qu'à de nouvelles valeurs, indépendantes du dernier appel.
Dans l'exemple ci-dessus, en raison de l'existence d'une fermeture, i dans a existera toujours après le retour de la fonction a. De cette façon, chaque fois que c() est exécuté, i sera la valeur de i qui est alertée après l'ajout. 1.
Alors imaginons une autre situation. Si a renvoie autre chose que la fonction b, la situation est complètement différente. Parce qu'après l'exécution de a, b n'est pas renvoyé au monde extérieur de a, mais n'est référencé que par a. À ce stade, a ne sera référencé que par b. Par conséquent, les fonctions a et b se réfèrent l'une à l'autre mais ne sont pas perturbées. par le monde extérieur (référencé par le monde extérieur), les fonctions a et b seront recyclées par GC. (Le mécanisme de récupération de place de Javascript sera présenté en détail plus tard)
Si nous voulons avoir une compréhension plus approfondie des fermetures et de la relation entre la fonction a et la fonction imbriquée b, nous devons introduire plusieurs autres concepts : le contexte d'exécution du fonction ), objet actif (objet d'appel), portée (portée), chaîne de portée (chaîne de portée). Prenons comme exemple le processus de la fonction a, de la définition à l'exécution, pour illustrer ces concepts.
1. Lorsque définit la fonction a, l'interpréteur js définira la chaîne de portée de la fonction a sur "l'environnement" où se trouve a lorsque définit a , si a est un fonction globale, il n'y a que l'objet window dans la chaîne de portée.
2. Lors de l'exécution de la fonction a, a entrera dans le contexte d'exécution correspondant.
3. Dans le processus de création de l'environnement d'exécution, un attribut de portée sera d'abord ajouté à a, c'est-à-dire la portée de a, et sa valeur est la chaîne de portée à l'étape 1. Autrement dit, la chaîne de portées de a.scope=a.
4. Ensuite, l'environnement d'exécution créera un objet d'appel. Un objet actif est également un objet qui possède des propriétés, mais il n'a pas de prototype et n'est pas accessible directement via le code Javascript. Après avoir créé l'objet actif, ajoutez l'objet actif en haut de la chaîne de portées 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 arguments sur l'objet actif, qui stocke les paramètres passés lors de l'appel de la fonction 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. Dans cette étape, la définition de la fonction b est terminée, donc tout comme à l'étape 3, la chaîne de portée de la fonction b est définie sur l'environnement dans lequel b est défini, c'est-à-dire la portée de a.
À ce stade, les étapes allant de la définition à l'exécution de l'ensemble de la fonction a sont terminées. À ce stade, a renvoie la référence de 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, ce qui signifie 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 dépend de 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 la même chose que les étapes ci-dessus. Par conséquent, la chaîne de portée de b lors de l'exécution contient 3 objets : l'objet actif de b, l'objet actif de a et l'objet fenêtre, comme le montre la figure suivante :
Comme le montre la figure, lorsque dans la fonction Lors de l'accès à une variable dans b, l'ordre de recherche est :
1. Recherchez d'abord son propre objet actif, et retournez s'il existe. S'il n'existe pas, il continuera à rechercher l'objet actif de la fonction a, et recherchez dans l'ordre jusqu'à ce qu'il soit trouvé.
2. Si la fonction b a un objet prototype prototype, elle recherchera d'abord son propre objet prototype après avoir recherché son propre objet actif, puis continuera la recherche. Il s'agit du mécanisme de recherche de variables en Javascript.
3. S'il est introuvable dans toute la chaîne de portée, undefined est renvoyé.
Résumé, deux mots importants sont mentionnés dans ce paragraphe : la définition et l'exécution des fonctions. L'article mentionne que la portée d'une fonction est déterminée lorsque la fonction est définie, et non lorsqu'elle est exécutée (voir étapes 1 et 3). Utilisez un morceau de code pour illustrer ce problème :
function f(x) { var g = function () { return x; } return g; } var h = f(1); alert(h());
Dans ce code, la variable h pointe vers la fonction anonyme dans f (renvoyée par g).
· En supposant que la portée de la fonction h est déterminée en exécutant alert(h()), alors la chaîne de portée de h à ce moment est : l'objet actif de h ->l'objet actif de l'alerte->l'objet fenêtre.
· En supposant que la portée de la fonction h est déterminée lors de sa définition, c'est-à-dire que la fonction anonyme pointée par h voit sa portée déterminée lors de sa définition. Ensuite, pendant l'exécution, la chaîne de portée de h est : l'objet actif de h ->l'objet actif de f->l'objet fenêtre.
Si la première hypothèse est vraie, la valeur de sortie n'est pas définie ; si la deuxième hypothèse est vraie, la valeur de sortie est 1.
Les résultats en cours prouvent que la deuxième hypothèse est correcte, indiquant que la portée de la fonction est effectivement déterminée lorsque la fonction est définie.
4. Scénarios d'application de fermetures
Protégez la sécurité des variables au sein des fonctions. En prenant l'exemple initial comme exemple, i dans la fonction a n'est accessible que par la fonction b et n'est pas accessible par d'autres moyens, protégeant ainsi la sécurité de i.
1. Conserver une variable en mémoire. Toujours comme dans l'exemple précédent, en raison de la fermeture, i dans la fonction a existe toujours en mémoire, donc à chaque fois que c() est exécuté, i sera incrémenté de 1.
2. Implémentez les propriétés et les méthodes privées JS en protégeant la sécurité des variables (non accessibles en externe)
Les propriétés et méthodes privées ne sont pas accessibles en dehors du constructeur
function Constructor(...) { var that = this; var membername = value; function membername(...) {...} }
Les trois points ci-dessus constituent les scénarios d'application les plus élémentaires des fermetures, et de nombreux cas classiques en découlent.
5. Le mécanisme de garbage collection de Javascript
En Javascript, si un objet n'est plus référencé, alors l'objet sera recyclé par le GC. Si deux objets font référence l'un à l'autre et ne sont plus référencés par un tiers, alors les deux objets qui font référence l'un à l'autre seront également recyclés. Parce que la fonction a est référencée par b, et b est référencé par c en dehors de a, c'est pourquoi la fonction a ne sera pas recyclée après exécution.
6. Conclusion
Comprendre les fermetures Javascript est le seul moyen de devenir un programmeur JS avancé. Ce n'est qu'en comprenant son interprétation et son mécanisme de fonctionnement que vous pourrez écrire du code plus sûr et plus élégant.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!