Article original : JavaScript Closure Tutorial – How Closures and Lexical Scope Work in JS

Par Dave Gray

En JavaScript, les gens confondent souvent les fermetures avec la portée lexicale.

La portée lexicale est une partie importante des fermetures, mais ce n'est pas une fermeture en soi.

Les fermetures sont un concept avancé qui est également un sujet fréquent des entretiens techniques.

Vous devriez avoir une compréhension fondamentale des fonctions avant d'essayer de comprendre les fermetures.

Après avoir lu cet article, j'espère vous avoir aidé à apprendre ce qui suit :

  • La différence entre la portée lexicale et les fermetures.
  • Pourquoi les fermetures nécessitent une portée lexicale.
  • Comment donner un exemple de fermeture lors du processus d'entretien.

Qu'est-ce que la portée lexicale en JavaScript ?

La portée lexicale décrit comment les fonctions imbriquées (également connues sous le nom de "fonctions enfants") ont accès aux variables définies dans les portées parent.

const myFunction = () => {
     let myValue = 2;
     console.log(myValue);

     const childFunction = () => {
          console.log(myValue += 1);
     }

     childFunction();
}

myFunction();

Dans cet exemple, childFunction a accès à la variable myValue qui est définie dans la portée parent de myFunction.

La portée lexicale de childFunction permet l'accès à la portée parent.

Qu'est-ce qu'une fermeture en JavaScript ?

w3Schools.com offre une excellente définition de ce qu'est une fermeture :

Une fermeture est une fonction ayant accès à la portée parent, même après que la fonction parent a été fermée.

Regardons la première partie de la phrase avant la virgule :

...une fonction ayant accès à la portée parent

Cela décrit la portée lexicale !

Mais nous avons besoin de la deuxième partie de la définition pour donner un exemple de fermeture...

...même après que la fonction parent a été fermée.

Regardons un exemple de fermeture :

const myFunction = () => {
     let myValue = 2;
     console.log(myValue);

     const childFunction = () => {
          console.log(myValue += 1);
     }

     return childFunction;
}

const result = myFunction();
console.log(result);
result();
result();
result();

Copiez le code d'exemple ci-dessus et essayez-le.

Décortiquons ce qui se passe...

Dans cette révision, myFunction retourne childFunction au lieu de l'appeler.

Par conséquent, lorsque result est défini égal à myFunction(), l'instruction de console à l'intérieur de myFunction est enregistrée, mais pas l'instruction à l'intérieur de childFunction.

childFunction n'est pas appelée à l'action.

Au lieu de cela, elle est retournée et conservée dans result.

De plus, nous devons réaliser que myFunction a été fermée après avoir été appelée.

La ligne avec console.log(result) devrait montrer dans la console que result contient maintenant la valeur de fonction anonyme qui était childFunction.

Maintenant, lorsque nous appelons result(), nous appelons la fonction anonyme qui était assignée à childFunction.

En tant qu'enfant de myFunction, cette fonction anonyme a accès à la variable myValue à l'intérieur de myFunction même après qu'elle a été fermée !

La fermeture que nous avons créée permet maintenant de continuer à augmenter la valeur de la variable myValue chaque fois que nous appelons result().

Prenez votre temps avec les fermetures

Les fermetures sont considérées comme un concept avancé pour de bonnes raisons.

Même avec une explication étape par étape de ce qu'est une fermeture, ce concept peut prendre du temps à comprendre.

Ne vous précipitez pas pour comprendre et ne soyez pas dur avec vous-même si cela n'a pas de sens au début.

Lorsque vous comprendrez pleinement les fermetures, vous pourriez vous sentir comme Neo lorsqu'il voit la Matrice. Vous verrez de nouvelles possibilités de code et réaliserez qu'elles étaient là tout le temps !

Je vous laisse avec un tutoriel sur les fermetures de ma chaîne YouTube. J'approfondis un peu plus et je fournis quelques exemples supplémentaires de fermetures pour construire la discussion dans cet article.