Maison  >  Article  >  interface Web  >  Comprendre les fermetures en JavaScript

Comprendre les fermetures en JavaScript

PHPz
PHPzoriginal
2024-08-24 11:11:021008parcourir

Understanding Closures in JavaScript

Les fermetures sont un concept fondamental en JavaScript qui peut avoir un impact significatif sur la façon dont vous écrivez et comprenez votre code. Essentiellement, une fermeture permet à une fonction d'accéder à des variables depuis sa portée externe même après la fin de son exécution. Cette fonctionnalité peut être incroyablement puissante, mais elle nécessite également une solide compréhension pour être utilisée efficacement. Entrons dans les détails.

Qu’est-ce qu’une fermeture ?

Une fermeture est une fonction qui capture l'environnement lexical dans lequel elle a été créée. Cela signifie que la fonction conserve l'accès aux variables depuis sa portée externe, même après que la fonction externe a terminé son exécution. En JavaScript, des fermetures sont créées chaque fois qu'une fonction est définie dans une autre fonction.

Exemple de base

Pour comprendre les fermetures, considérons un exemple simple :

function outerFunction() {
    let outerVariable = 'I am an outer variable';

    function innerFunction() {
        console.log(outerVariable); // Inner function can access the outer variable
    }

    return innerFunction;
}

const myClosure = outerFunction();
myClosure(); // Logs: "I am an outer variable"

Dans cet exemple :

  1. externalFunction déclare une variable locale externalVariable et une fonction interne innerFunction.
  2. innerFunction enregistre externalVariable, démontrant l'accès à la variable externe.
  3. externalFunction renvoie innerFunction, créant une fermeture.
  4. myClosure, qui contient la référence à innerFunction, a toujours accès à externalVariable même après la fin de externalFunction.

Portée lexicale et fermetures

La portée lexicale de JavaScript signifie que la portée d'une fonction est déterminée par l'endroit où elle est définie, et non par l'endroit où elle est appelée. Les fermetures exploitent ce mécanisme de portée, permettant aux fonctions d'accéder aux variables depuis leurs portées externes même après le retour de la fonction externe.

Exemple pratique : variables privées

Les fermetures sont souvent utilisées pour créer des variables privées, qui sont des variables auxquelles on ne peut pas accéder depuis l'extérieur de leur fonction contenant :

function createCounter() {
    let count = 0;

    return {
        increment: function() {
            count++;
            return count;
        },
        decrement: function() {
            count--;
            return count;
        }
    };
}

const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1

Ici :

  1. createCounter initialise count et renvoie un objet avec les méthodes d'incrémentation et de décrémentation.
  2. Les deux méthodes forment des fermetures qui capturent et modifient le décompte, qui reste privé.

Exemple avancé : itérateurs

Les fermetures peuvent également être utilisées pour créer des itérateurs avec état, qui maintiennent l'état interne lors des appels de fonction :

function createIterator(array) {
    let index = 0;

    return {
        next: function() {
            if (index < array.length) {
                return { value: array[index++], done: false };
            } else {
                return { value: undefined, done: true };
            }
        }
    };
}

const iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

Dans cet exemple :

  1. createIterator capture le tableau et l'index dans une fermeture.
  2. La méthode suivante utilise l'index capturé pour renvoyer les éléments du tableau un par un.

Piège courant : fermetures en boucles

Les fermetures peuvent parfois conduire à un comportement inattendu lorsqu'elles sont utilisées dans des boucles, en particulier avec des opérations asynchrones. Voici un exemple illustrant le problème :

Utiliser var
for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}
// Logs: 5 5 5 5 5

Dans ce cas :

  1. La boucle se termine et i finit par être 5.
  2. Tous les rappels setTimeout font référence au même i, qui est 5.
Utiliser let
for (let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}
// Logs: 0 1 2 3 4

Ici :

  1. let crée un nouveau i de portée bloc pour chaque itération.
  2. Chaque rappel setTimeout capture un i différent, ce qui donne le résultat attendu.

Résumé

  • Fermeture : Une fonction qui se souvient et peut accéder à son environnement lexical.
  • Portée lexicale : les fonctions sont définies en fonction de l'endroit où elles sont définies et non appelées.
  • Variables privées : les fermetures peuvent encapsuler et protéger les variables.
  • Itérateurs : les fermetures peuvent maintenir l'état et fournir un accès séquentiel aux données.
  • Piège des boucles : soyez prudent avec var dans les boucles et préférez let pour éviter un comportement inattendu.

Comprendre les fermetures et leurs nuances améliorera votre capacité à écrire du code JavaScript plus puissant et plus maintenable. Utilisez ces principes à bon escient et vous serez en mesure de tirer parti des fermetures pour résoudre efficacement des problèmes complexes.

Suivez-moi sur : Github Linkedin

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn