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.