Maison >interface Web >js tutoriel >Introduction détaillée à la fermeture (Closure) dans les compétences JavaScript_javascript
La fermeture est une fonctionnalité importante en JavaScript. Son rôle principal est de sauvegarder les informations lors de l'exécution de la fonction. En JavaScript, de nombreuses fonctionnalités des fermetures proviennent de la chaîne de portée lors des appels de fonction.
Chaîne de portée des objets et variables d'appel de fonction
Pour chaque appel de fonction en JavaScript, JavaScript créera un objet local pour stocker les variables locales définies dans la fonction ; s'il y a une fonction imbriquée définie à l'intérieur de la fonction, alors JavaScript définira un objet local imbriqué au-dessus d'un objet déjà imbriqué. objet local défini. Pour une fonction, il y a autant de couches d’objets locaux imbriqués qu’il y a de couches de définitions de fonctions imbriquées à l’intérieur. Cet objet local est appelé "objet d'appel de fonction" ("objet d'appel" dans ECMAScript 3, renommé "enregistrement d'environnement déclaratif" dans ECMAScript 5, mais personnellement, je pense que le nom dans ECMAScript 3 est plus facile à comprendre). Prenons l'exemple de l'appel de fonction suivant :
Dans cet exemple simple, lorsque la fonction f() est appelée, JavaScript créera un objet d'appel de la fonction f() (appelons-le f_invokeObj). Il y a deux attributs à l'intérieur de l'objet f_invokeObj : a et x ; en exécutant f(), la valeur de a est 10 et la valeur de x est 6, donc le résultat final renvoyé est 60. L'icône est la suivante :
Lorsque l'imbrication de fonctions existe, JavaScript créera plusieurs objets d'appel de fonction :
Dans cet exemple, lorsque la fonction f() est appelée, JavaScript créera un objet d'appel (f_invokeObj) de la fonction f(), qui possède deux attributs internes a et x. La valeur de a est 10 et la valeur de x est. 6 ; exécutez f(), JavaScript analysera et définira la fonction g() dans la fonction f(), et créera l'objet appelant (g_invokeObj) de g(), qui a un attribut interne b, et la valeur b est la identique au paramètre entrant x, qui est 6 , donc le résultat final renvoyé est 360. L'icône est la suivante :
Comme vous pouvez le voir, les objets d'appel de fonction forment une chaîne. Lorsque la fonction intégrée g() est en cours d'exécution et doit obtenir la valeur de la variable, la recherche commencera à partir de l'objet d'appel de fonction le plus proche. S'il ne peut pas être recherché, elle recherchera d'autres objets d'appel le long de la chaîne d'objets d'appel de fonction. la soi-disant « chaîne à portée variable ». Si la même variable apparaît dans deux objets d'appel de fonction, la fonction prendra la valeur de la variable dans l'objet d'appel le plus proche d'elle :
Dans l'exemple ci-dessus, la variable a existe à la fois dans l'objet appelant de la fonction g() (g_invokeObj) et dans l'objet appelant de la fonction f() (f_invokeObj) et la valeur de a est différente lorsque la fonction g() est. run, in g() La valeur de a utilisée à l'intérieur de la fonction est 1, tandis que la valeur de a utilisée en dehors de la fonction g() est 10. La chaîne d'objets d'appel de fonction illustrée dans la figure est la suivante :
Qu'est-ce qu'une fermeture ?
Toutes les fonctions (fonctions) en JavaScript sont des objets, et lorsqu'une fonction est définie, une chaîne d'objets d'appel de fonction correspondante sera générée. Une définition de fonction correspond à une chaîne d'objets d'appel de fonction. Tant que l'objet de fonction existe, l'objet d'appel de fonction correspondant existe ; une fois qu'une fonction n'est plus utilisée, l'objet d'appel de fonction correspondant sera récupéré et cette combinaison un-à-un entre l'objet de fonction et l'objet d'appel de fonction ; chaîne, appelez-la simplement "fermeture". Dans l'exemple ci-dessus de la fonction f() et de la fonction g(), il y a deux fermetures : l'objet fonction f() et l'objet f_invokeObj forment une fermeture, et l'objet fonction g() et la chaîne d'objets g_invokeObj-f_invokeObj. former ensemble La deuxième fermeture. Lorsque la fonction g() termine son exécution, la fermeture g() est récupérée car la fonction g() n'est plus utilisée plus tard, lorsque la fonction f() termine son exécution, f() est fermée pour la même raison ; Le colis a également été ramassé.
De la définition de la fermeture, nous pouvons conclure que toutes les fonctions JavaScript sont des fermetures après définition - parce que toutes les fonctions sont des objets, toutes les fonctions ont également leur chaîne d'objets appelants correspondante après exécution.
Cependant, c'est dans le cas des fonctions imbriquées que les fermetures prennent tout leur sens. Étant donné que la fonction en ligne est définie lors de l'exécution de la fonction externe, les valeurs des variables enregistrées lors de la fermeture de la fonction en ligne (en particulier les valeurs des variables locales de la fonction externe) sont les valeurs lors de cette exécution. Tant que l'objet fonction intégré existe toujours, sa fermeture existera toujours (les valeurs des variables dans la fermeture ne changeront pas), atteignant ainsi l'objectif de sauvegarder des informations sur le processus en cours d'exécution de la fonction. Prenons cet exemple :
Dans cet exemple, lorsque la fonction f() est exécutée, la fonction g() est définie et une fermeture de la fonction g() est créée. La fermeture g() contient la chaîne d'objets g_invokeObj-f_invokeObj, économisant ainsi f(). La valeur de la variable a pendant l'exécution de la fonction. Lorsque l'instruction console.log() est exécutée, puisque l'objet fonction g existe toujours, la fermeture g() existe toujours ; lors de l'exécution de l'objet fonction g qui existe toujours, JavaScript utilisera la fermeture g() qui existe toujours et Get la valeur de la variable a ("à l'intérieur") de celle-ci.