JavaScript - Fermetures (Closures)

Salut à toi, futurs superstars du codage ! ? Aujourd'hui, nous allons entreprendre un voyage passionnant à travers le monde des fermetures (closures) en JavaScript. Ne t'inquiète pas si cela semble un peu effrayant - je promets que d'ici la fin de ce tutoriel, tu seras un expert en fermetures ! Alors, prends ta boisson favorite, installe-toi confortablement, et plongeons dedans !

JavaScript - Closures

Qu'est-ce qu'une fermeture (Closure) ?

Imagine que tu as une boîte magique qui se souvient de tout ce qu'il y a à l'intérieur, même après que tu l'as fermée. C'est essentiellement ce qu'est une fermeture en JavaScript !

Une fermeture est une fonction qui a accès aux variables de son scope lexical externe (enclosing), même après que la fonction externe a retourné une valeur. C'est comme si la fonction portait un petit sac à dos de variables qu'elle peut utiliser whenever she needs them.

Regardons un exemple simple :

function fonctionExterne(x) {
let y = 10;
function fonctionInterne() {
console.log(x + y);
}
return fonctionInterne;
}

let fermeture = fonctionExterne(5);
fermeture(); // Outputs: 15

Dans cet exemple, fonctionInterne est une fermeture. Elle "se souvient" des valeurs de x et y même après que fonctionExterne a terminé son exécution.

Portée Lexicale

Avant de plonger plus profondément dans les fermetures, nous devons comprendre la portée lexicale. C'est un terme fancy qui signifie simplement qu'une fonction peut accéder aux variables de son scope externe.

let nom = "Alice";

function saluer() {
console.log("Bonjour, " + nom + " !");
}

saluer(); // Outputs: Bonjour, Alice !

Ici, saluer peut accéder à la variable nom grâce à la portée lexicale. C'est comme si saluer pouvait voir tout dans son environnement environnant.

Fonction嵌套 (Nested Function)

Les fermetures impliquent souvent des fonctions嵌套. Regardons un exemple :

function fonctionExterne() {
let count = 0;
function fonctionInterne() {
count++;
console.log(count);
}
return fonctionInterne;
}

let compteur = fonctionExterne();
compteur(); // Outputs: 1
compteur(); // Outputs: 2

Ici, fonctionInterne est嵌套e à l'intérieur de fonctionExterne. Le truc magique se produit parce que fonctionInterne se souvient de la variable count de son scope externe, même après que fonctionExterne a terminé son exécution.

Retour de Fonction

Une des choses cool à propos de JavaScript est que les fonctions peuvent retourner d'autres fonctions. C'est un aspect clé des fermetures.

function multiplieur(x) {
return function(y) {
return x * y;
};
}

let double = multiplieur(2);
console.log(double(5)); // Outputs: 10
console.log(double(3)); // Outputs: 6

Dans cet exemple, multiplieur retourne une fonction qui se souvient de la valeur de x. Cette fonction retournée est une fermeture.

Un Dilemme Compteur

Regardons un problème commun que les fermetures peuvent résoudre :

function creerCompteur() {
let count = 0;
return {
incrementer: function() {
count++;
},
getCompteur: function() {
return count;
}
};
}

let compteur = creerCompteur();
compteur.incrementer();
compteur.incrementer();
console.log(compteur.getCompteur()); // Outputs: 2

Ici, la fermeture nous permet d'avoir des variables privées (count) qui ne peuvent être accédées que par les méthodes fournies.

Exemple : Fermetures JavaScript

Plongons dans un exemple plus complexe pour bien solidifier notre compréhension :

function creerAdditionneur(x) {
return function(y) {
return x + y;
};
}

let ajouter5 = creerAdditionneur(5);
let ajouter10 = creerAdditionneur(10);

console.log(ajouter5(2));  // Outputs: 7
console.log(ajouter10(2)); // Outputs: 12

Dans cet exemple, creerAdditionneur crée une fermeture qui "se souvient" de la valeur de x. Nous pouvons créer plusieurs fonctions additionneuses avec différents valeurs prédéfinies.

Exemple

Voici un autre exemple pratique des fermetures :

function creerSalutations(salutation) {
return function(nom) {
console.log(salutation + ", " + nom + " !");
};
}

let saluerHello = creerSalutations("Bonjour");
let saluerHi = creerSalutations("Salut");

saluerHello("Alice"); // Outputs: Bonjour, Alice !
saluerHi("Bob");      // Outputs: Salut, Bob !

Cet exemple montre comment les fermetures peuvent être utilisées pour créer des fonctions personnalisées.

Avantages des Fermetures

Les fermetures offrent plusieurs avantages :

  1. Confidentialité des données
  2. Usines de fonctions
  3. Maintien de l'état

Regardons ces avantages dans un tableau :

Avantage Description Exemple
Confidentialité des données Les fermetures peuvent créer des variables privées function compteur() { let count = 0; return { incrementer: () => ++count, getValue: () => count }; }
Usines de fonctions Créer des fonctions avec des paramètres prédéfinis function multiplier(x) { return (y) => x * y; }
Maintien de l'état Suivre les données entre les appels de fonction function creerJeu() { let score = 0; return { ajouterPoint: () => ++score, getScore: () => score }; }

Et voilà, les amis ! Nous avons fait le voyage à travers le pays des fermetures, des bases aux concepts plus avancés. Souviens-toi, comme toute compétence, maîtriser les fermetures nécessite de la pratique. Ne t' décourage pas si cela ne fonctionne pas immédiatement - continue de coder, continue d'expérimenter, et bientôt tu maîtriseras le pouvoir des fermetures comme un véritable magicien JavaScript ! ?‍♂️✨

Credits: Image by storyset