Pour les développeurs JavaScript débutants, comprendre le concept de "closure" peut sembler un peu intimidant au départ. Cependant, une fois que vous avez une bonne compréhension de ce concept, vous pouvez commencer à tirer parti de cette fonctionnalité puissante pour écrire des codes plus efficaces et fonctionnels. Dans cet article, nous allons expliquer ce qu'est une closure en JavaScript et donner un exemple de code pour illustrer ce concept.
Qu'est-ce qu'une closure en JavaScript ?
En termes simples, une closure est une fonction qui a accès à une variable définie dans une fonction parente qui a déjà été exécutée.
Une closure est une fonction qui mémorise le contexte de son appel. Le contexte est l'état de son environnement. C'est une sorte de photo de l'ensemble des variables accessibles à partir de cette fonction au moment de sa création.
Cette fonction peut ensuite accéder et manipuler ces variables même si la fonction parente n'est plus en cours d'exécution.
Prenons un exemple pour mieux comprendre ce concept. Supposons que nous ayons une fonction appelée "outerFunction" qui contient une variable appelée "count". Cette fonction renvoie une fonction qui incrémente le "count" de 1 chaque fois qu'elle est appelée :
function outerFunction() {
let count = 0;
function innerFunction() {
count++;
console.log(count);
}
return innerFunction;
}
const incrementCount = outerFunction();
incrementCount(); // 1
incrementCount(); // 2
incrementCount(); // 3
Dans cet exemple, "outerFunction" contient la variable "count" et la fonction "innerFunction". "innerFunction" est retournée à partir de "outerFunction" et stockée dans la variable "incrementCount". Lorsque "incrementCount" est appelée, elle incrémente le "count" de 1 et le renvoie à la console. Nous pouvons appeler "incrementCount" plusieurs fois et chaque fois qu'elle est appelée, elle conserve l'état de "count" et l'incrémente.
On dit qure la fonction "innerFunction" est une closure car elle a accès à la variable "count" définie dans la fonction parente "outerFunction" même si cette fonction n'est plus en cours d'exécution.
Pourquoi les closures sont-elles utiles ?
Les closures sont utiles car elles permettent de créer des fonctions qui conservent leur état entre les appels. Cela peut être utile dans de nombreuses situations, notamment pour :
- Créer des fonctions réutilisables qui ont besoin d'un état conservé.
- Éviter la pollution de l'espace global en encapsulant des variables privées à l'intérieur de la fonction.
- Utiliser des fonctions de rappel (les callbacks) qui nécessitent un état conservé.
Les closures permettent l'encapsulation, et elles permettent le fonctionnement asynchrone de JavaScript qui utilise massivement les callbacks [lien vers l'article sur les callbacks].
Exemple de code utilisant une closure
Considérons l'exemple suivant où nous avons une fonction qui retourne une autre fonction qui utilise une variable "name" :
function sayHello(name) {
return function() {
console.log(`Hello, ${name}!`);
}
}
const helloAlice = sayHello("Alice");
const helloBob = sayHello("Bob");
helloAlice(); // Hello, Alice!
helloBob(); // Hello, Bob!
Dans cet exemple, nous avons une fonction appelée sayHello
qui prend un argument name
.
Cette fonction retourne une autre fonction (une closure) qui utilise la variable name
pour dire "Hello name
.
De cette façon, nous pouvons écrire un code plus lisible avec une approche fonctionnelle : des fonctions génériques peuvent retourner des closures spécifiques utilisables dans un contexte particulier.
Les closures contribuent à faire des fonctions des [citoyens de premières classe] dans le langage Javascript.