Portée lexicale JavaScript et fermeture



Traduction de l' environnement JavaScript, portée lexicale et fermetures .

Parlons de l'environnement. Notre immense planète est une pour tous. Lors de la construction d'une nouvelle usine chimique, il serait bon de l'isoler afin que tous les processus internes ne quittent pas ses frontières. On peut dire que l'environnement et le microclimat de cette plante sont isolés de l'environnement extérieur.

Le programme est organisé de la même manière. Ce que vous créez en externe - fonctions externes, instructions conditionnelles, boucles et autres blocs - est un environnement global externe.



L' age constant, la fonction multiplier et la variable de result trouvent dans l'environnement externe. Ces composants ont une portée mondiale. Une étendue est la zone dans laquelle un composant est disponible.

Dans ce cas, x est une constante à l'intérieur de la fonction multiplier . Puisqu'il est à l'intérieur d'un bloc de code, il s'agit d'une constante locale et non globale. Il n'est visible qu'à l'intérieur de la fonction, mais pas à l'extérieur - sa portée est locale.

La fonction multiplier a un autre composant de la portée locale - c'est l'argument num . La définir est plus difficile qu'une constante ou une variable, mais elle se comporte à peu près comme une variable locale.

Nous n'avons pas d'accès externe à x - il ne semble pas exister:



console.log appelé x dans un environnement global dans lequel il n'est pas défini. En conséquence, nous avons obtenu une ReferenceError.

Nous pouvons définir x globalement:



Nous avons un x global avec une valeur connue, mais le x local dans la fonction multiplier n'est encore visible que de l'intérieur. Ces x ne sont connectés d'aucune façon - ils sont dans des environnements différents. Malgré le même nom, ils ne se mélangent pas.

Tout bloc de code entre accolades devient un environnement local. Voici un exemple d'utilisation de if :



La même chose se produit avec les boucles while et for .

Donc local signifie invisible de l'extérieur. Autrement dit, le global est visible partout, même à l'intérieur des objets? Oui!



La variable globale a a changé dans la fonction changer . La fonction ne prend effet que lorsqu'elle est appelée, pas lorsqu'elle est définie, donc initialement a=0 , et lorsqu'elle est appelée, le changer prend la valeur 1 .

Il est facile de succomber à la tentation et de tout mettre dans une portée mondiale, en oubliant toutes les complexités des environnements individuels - mais c'est une idée terrible. Les variables globales rendent votre code extrêmement fragile, n'importe quel élément peut en casser un autre à tout moment. Par conséquent, n'utilisez pas la portée globale et gardez tout en place.

Partie II Portée lexicale


Jetez un œil à ce programme:



La fonction multiplier renvoie les résultats de la multiplication a et b . a donné en interne, mais b ne l' b pas.

Lorsque vous essayez d'effectuer l'opération de multiplication a a*b , JavaScript recherche les valeurs de a et b . Il commence à chercher à l'intérieur, puis sort à l'extérieur, étudiant un domaine après l'autre, jusqu'à ce qu'il trouve ce qu'il cherchait, ou ne comprenne pas qu'il est impossible de trouver.

Par conséquent, dans cet exemple, JavaScript commence à rechercher a à l'intérieur de la zone locale - à l'intérieur de la fonction multiplier . Il trouve immédiatement la valeur et passe à b . b qu'il ne trouvera pas dans l'environnement local, il va donc au-delà. Là, il apprend que b est 10 . Donc, a*b devient 5*10 , puis 50 .

Ce morceau de code pourrait être à l'intérieur d'une autre fonction, qui est également à l'intérieur d'une autre fonction. Sans trouver b dans la première couche, JavaScript continuerait de rechercher de plus en plus de nouvelles et nouvelles couches.

Veuillez noter que a=7 n'affecte en rien le résultat des calculs: la valeur de a été trouvée à l'intérieur, par conséquent, le a externe ne joue aucun rôle.

C'est ce qu'on appelle la portée lexicale. La portée de tout composant est déterminée par l'emplacement de ce composant dans le code et les blocs imbriqués ont accès à des zones externes.

Partie III. Court-circuits


Les environnements et les étendues sont pris en charge par la plupart des langages de programmation, et ce mécanisme permet l'introduction de fermetures. La fermeture est intrinsèquement une fonction qui «se souvient» des entités externes utilisées en interne.

Avant de continuer, rappelons comment les fonctions sont créées et utilisées:



f est une fonction assez inutile qui renvoie toujours 0 . L'ensemble se compose de deux parties - une constante et la fonction elle-même.

Il est important de se rappeler qu'il s'agit de composants distincts. Le premier composant est une constante appelée f . Sa valeur peut être un nombre ou une valeur de chaîne. Dans ce cas, la valeur est une fonction.

Dans les leçons précédentes, nous avons cité une analogie: les constantes sont comme des feuilles de papier avec un nom d'un côté et une valeur de l'autre. Ainsi, f est un morceau de papier avec f écrit d'un côté et une description de la fonction en cours de lancement de l'autre.

Lors de l'appel de cette fonction:



Une nouvelle «boîte» est créée sur la base de la description d'une feuille de papier.

Retour aux fermetures. Voici un exemple de code.



La fonction createPrinter crée une constante de name , puis une fonction appelée printName . Les deux sont locaux à la fonction createPrinter et ne sont disponibles qu'à l'intérieur.

printName lui-même n'a printName composants locaux, mais il a accès à l'étendue où il est créé et à l'environnement externe, où un name est attribué à la constante.

La fonction createPrinter renvoie la fonction printName . Rappelez-vous que les définitions de fonctions sont des descriptions de fonctions en cours d'exécution; ce ne sont que des éléments de données, comme des nombres ou des chaînes. Par conséquent, nous pouvons retourner la définition d'une fonction de la même manière que nous renvoyons des nombres.

Dans la portée externe, nous créons la constante myPrinter et lui définissons la valeur de retour en tant que createPrinter . Une fonction est renvoyée, donc myPrinter devient également une fonction. Lorsque vous l'appelez, King apparaîtra à l'écran.

Voici la chose amusante: la constante de name été créée dans la fonction createPrinter . La fonction a été appelée et exécutée. Comme vous le savez, lorsqu'une fonction a fini de fonctionner, elle cesse d'exister. La boîte magique disparaît avec tout le contenu.

Mais il a renvoyé une autre fonction qui se souvenait en quelque sorte de la constante de name . Ainsi, lors de l'appel de myPrinter nous avons obtenu King - la valeur dont la fonction se souvient, malgré le fait que cette zone n'existe plus.

La fonction createPrinter par createPrinter est appelée fermeture. Une fermeture est une combinaison d'une fonction et de l'environnement dans lequel elle a été définie. La fonction «renfermait» en soi certaines informations reçues dans le périmètre.

Cela peut sembler étrange de JavaScript, mais une utilisation judicieuse des fermetures peut aider à rendre le code plus agréable, propre et lisible. Le principe du renvoi de fonctions, comme le renvoi de nombres et de valeurs de chaîne, vous donne plus de liberté de manœuvre.

Source: https://habr.com/ru/post/fr460861/


All Articles