6.1 Concept des closures
Les closures sont l'une des concepts les plus puissants et importants en JavaScript. Elles permettent aux fonctions de se souvenir de leur environnement lexical même après avoir été exécutées. Dans cette leçon, nous allons aborder le concept des closures, leurs particularités et donner divers exemples de leur utilisation.
Closure en JavaScript — c'est une combinaison d'une fonction et de l'environnement lexical dans lequel cette fonction a été déclarée. La closure permet à une fonction de "se souvenir" et d'accéder aux variables et autres fonctions de sa portée extérieure même après que la fonction extérieure ait été exécutée.
Caractéristiques principales des closures :
- Environnement lexical : le contexte dans lequel la fonction a été déclarée, y compris toutes les variables disponibles au moment de la déclaration.
- Sauvegarde du contexte : une fonction avec une closure peut conserver l'accès aux variables de la portée extérieure même après la fin de l'exécution de cette fonction extérieure.
6.2 Exemples de travail des closures
Exemple 1 : Closure simple
Dans cet exemple, innerFunction()
a accès à la variable outerVariable
de sa
portée extérieure même après l'exécution de outerFunction()
.
function outerFunction() {
let outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // Affichera : I am from the outer function
Exemple 2 : Compteur en utilisant une closure
Dans cet exemple, la fonction compteur préserve la valeur de la variable count
et l'incrémente à chaque appel.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // Affichera : 1
console.log(counter()); // Affichera : 2
console.log(counter()); // Affichera : 3
Exemple 3 : Closure en boucle
Les closures sont souvent utilisées pour préserver les valeurs des variables dans les boucles.
Dans cet exemple, chaque fonction à l'intérieur du tableau arr
"se souvient" de la valeur de la variable i
au moment de sa création grâce à la portée de bloc de let
:
function createArrayWithClosures() {
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
const closures = createArrayWithClosures();
closures[0](); // Affichera : 0
closures[1](); // Affichera : 1
closures[2](); // Affichera : 2
6.3 Scénarios complexes d'utilisation des closures
Exemple 1 : Application partielle de fonction (partial application)
Les closures permettent de créer des fonctions partiellement appliquées, en gardant certains arguments fixes.
Dans cet exemple, la fonction multiply()
retourne une fonction qui multiplie son argument b
par l'argument fixé a
.
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // Affichera : 10
console.log(double(10)); // Affichera : 20
Exemple 2 : Cachage de données (data hiding)
Les closures peuvent être utilisées pour créer des variables et méthodes privées.
Dans cet exemple, les variables _name
et _age
sont privées et accessibles uniquement via les méthodes de l'objet :
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function() {
return _name;
},
getAge: function() {
return _age;
},
setName: function(newName) {
_name = newName;
},
setAge: function(newAge) {
_age = newAge;
}
};
}
const person = createPerson('John', 30);
console.log(person.getName()); // Affichera : John
person.setName('Jane');
console.log(person.getName()); // Affichera : Jane
console.log(person.getAge()); // Affichera : 30
Exemple 3 : Mémorisation
Mémorisation — c'est une technique d'optimisation où les résultats d'une fonction sont stockés pour éviter des recalculs pour les mêmes entrées.
Dans cet exemple, la fonction memoize()
utilise une closure pour stocker le cache des résultats calculés de la fonction fn()
:
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function slowFunction(num) {
console.log('Computing...');
return num * 2;
}
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // Affichera : Computing... 10
console.log(memoizedFunction(5)); // Affichera : 10 (résultat pris du cache)
GO TO FULL VERSION