Fermetures JavaScript

Les variables JavaScript peuvent appartenir à :

L' espace de noms local ou l' espace de noms global

Les variables globales peuvent être rendues locales (privées) grâce aux fermetures .

Les fermetures permettent à une fonction d'avoir des variables "privées".

Variables Locales

Une variable locale est une variable "privée" définie à l'intérieur d'une fonction.

Une fonction peut accéder à toutes les variables dans l' espace de noms local .

Exemple

a est une variable locale définie à l'intérieur de la fonction :

function myFunction() {
let a = 4;
return a * a;
}
Essayez-le vous-même »

Variables Globales

Une variable globale est une variable "publique" définie à l'extérieur d'une fonction.

Une fonction peut accéder à toutes les variables dans l' espace de noms global :

Exemple

a est une variable globale définie à l'extérieur de la fonction :

let a = 4;
function myFunction() {
return a * a;
}
Essayez-le vous-même »

Dans une page web, les variables globales appartiennent à la page.

Les variables globales peuvent être utilisées (ou modifiées) par tous les scripts de la page.

Une variable locale ne peut être utilisée que dans la fonction où elle est définie. Elle est privée et cachée des autres fonctions et du reste du code de script.

Les variables globales et locales ayant le même nom sont des variables différentes. Modifier l'une ne modifie pas l'autre.

Remarque

Les variables non déclarées (créées sans un mot-clé var , let , const ), sont toujours globales , même si elles sont créées à l'intérieur d'une fonction.

Exemple

La variable a est une variable globale car elle est non déclarée :

function myFunction() {
a = 4;
}
Essayez-le vous-même »


Durée de Vie des Variables

Les variables globales vivent jusqu'à ce que la page soit abandonnée, comme lorsque vous naviguez vers une autre page ou fermez la fenêtre.

Les variables locales ont une courte durée de vie. Elles sont créées lorsque la fonction est invoquée, et supprimées lorsque la fonction est terminée.


Un Dilemme de Compteur

Supposons que vous souhaitiez utiliser une variable pour compter quelque chose, et que vous vouliez que ce compteur soit disponible pour tout le monde (toutes les fonctions).

Vous pourriez utiliser une variable globale, et une fonction pour augmenter le compteur :

Exemple

// Initier le compteur
let counter = 0;

// Fonction pour incrémenter le compteur
function add() {
counter += 1;
}

// Appeler add() 3 fois
add();
add();
add();

// Le compteur devrait maintenant être 3
Essayez-le vous-même »

Avertissement !

Il y a un problème avec la solution ci-dessus : Tout code sur la page peut changer le compteur, sans appeler add() .

Le compteur devrait être local à la fonction add() , pour empêcher d'autres codes de le modifier :

Exemple

// Initier le compteur
let counter = 0;

// Fonction pour incrémenter le compteur
function add() {
let counter = 0;
counter += 1;
}

// Appeler add() 3 fois
add();
add();
add();

// Le compteur devrait maintenant être 3. Mais il est 0
Essayez-le vous-même »

Cela n'a pas fonctionné car nous affichons le compteur global au lieu du compteur local.

Nous pouvons supprimer le compteur global et accéder au compteur local en laissant la fonction le retourner :

Exemple

// Fonction pour incrémenter le compteur
function add() {
let counter = 0;
counter += 1;
return counter;
}

let x= 0;
// Appeler add() 3 fois
x = add();
x = add();
x = add();

// Le compteur devrait maintenant être 3. Mais il est 1.
Essayez-le vous-même »

Cela n'a pas fonctionné car nous réinitialisons le compteur local chaque fois que nous appelons la fonction.

Solution

Une fonction interne JavaScript peut résoudre cela.

Fonctions Imbriquées JavaScript

Toutes les fonctions ont accès à l'espace de noms global.

En fait, en JavaScript, toutes les fonctions ont accès à l'espace de noms "au-dessus" d'elles.

JavaScript prend en charge les fonctions imbriquées. Les fonctions imbriquées ont accès à l'espace de noms "au-dessus" d'elles.

Exemple

La fonction interne plus() a accès à la variable counter dans la fonction parente :

function add() {
let counter = 0;
function plus() {counter += 1;}
plus();
return counter;
}
Essayez-le vous-même »

Cela aurait pu résoudre le dilemme du compteur, si nous pouvions atteindre la fonction plus() de l'extérieur.

Nous devons également trouver un moyen d'exécuter counter = 0 une seule fois.

Solution

Nous avons besoin d'une fermeture.

Fermetures JavaScript

Exemple

function myCounter() {
let counter = 0;
return function() {
counter++;
return counter;
};
}
const add = myCounter();
add();
add();
add();

// le compteur est maintenant 3
Essayez-le vous-même »

Exemple Expliqué

La variable add est assignée à la valeur de retour d'une fonction.

La fonction ne s'exécute qu'une seule fois. Elle initialise le compteur à zéro (0) et retourne une expression de fonction.

De cette manière, add devient une fonction. La partie "merveilleuse" est qu'elle peut accéder au compteur dans son espace de noms parent.

Cela s'appelle une fermeture. Cela permet à une fonction d'avoir des variables " privées ".

Le compteur est protégé par l'espace de noms de la fonction myCounter et ne peut être modifié qu'en utilisant la fonction add.


Conclusion

Une fermeture est une fonction qui a accès à l'espace de noms parent, après que la fonction parente a été fermée.

Les fermetures ont historiquement été utilisées pour :

  • Créer des variables privées
  • Préserver l'état entre les appels de fonction
  • Simuler la portée de bloc avant que let et const n'existent
  • Implémenter certains modèles de conception comme le currying et la mémorisation

Remarque

L'ancien code JavaScript contiendra souvent des fermetures, mais le JavaScript moderne n'utilisera pas les fermetures aussi fréquemment qu'auparavant.

ECMAScript 2015 et les versions JavaScript ultérieures ont introduit de nouvelles fonctionnalités du langage qui offrent des alternatives aux fermetures.

Bien que les fermetures soient un concept puissant en JavaScript, les nouvelles fonctionnalités JavaScript rendent certains cas d'utilisation des fermetures moins nécessaires.