344 votes

Ce qui est une utilisation pratique pour une fermeture en JavaScript ?

Je vais essayer de mon mieux pour envelopper ma tête autour de JavaScript fermetures.

Je reçois en retour d'une fonction interne, il aura accès à toutes les variables définies dans son parent immédiat.

Où serait-ce utile pour moi? Peut-être que je n'ai pas encore reçu ma tête autour de lui encore. La plupart des exemples que j'ai vu en ligne ne fournit pas de monde réel de code, seulement de vagues exemples.

Quelqu'un peut-il m'indiquer une utilisation dans le monde réel d'une fermeture?

Est-ce, par exemple?

var warnUser = function (msg) {
    var calledCount = 0;
    return function() {
       calledCount++;
       alert(msg + '\nYou have been warned ' + calledCount + ' times.');
    };
};

var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();

281voto

Francisco Soto Points 5043

J’ai utilisé des fermetures pour faire des choses comme :

Comme vous pouvez le voir il, « a » est maintenant un objet avec une méthode getRecordFromdatabase (a.publicfunction()) dont privatefunction appels, qui n’existe qu’à l’intérieur de la clôture, vous ne pouvez pas appeler privatefunction directement, juste publicfunction().

Son un exemple minimal, mais peut-être que vous pouvez voir utilisations à elle ? Nous avons utilisé cela pour faire appliquer les méthodes public/privé.

73voto

Marcelo Cantos Points 91211

L'exemple que vous donnez est excellent. Les fermetures sont une abstraction mécanisme qui permet de séparer les préoccupations très proprement. Votre exemple est un cas de la séparation de l'instrumentation (comptage des appels) à partir de la sémantique (un rapport d'erreurs de l'API). D'autres utilisations incluent:

  1. En passant de paramétrer le comportement dans un algorithme classique d'ordre supérieur de la programmation):

    function proximity_sort(midpoint) {
        a.sort(function(a, b) { a -= midpoint; b -= midpoint; return a*a < b*b; });
    }
    
  2. La simulation de la programmation orientée objet:

    function counter() {
        var a = 0;
        return {
            inc: function() { ++a; },
            dec: function() { --a; },
            get: function() { return a; },
            reset: function() { a = 0; }
        }
    }
    
  3. La mise en œuvre exotique de contrôle de flux, tels que jQuery est la gestion des Événements et AJAX Api.

21voto

Andy E Points 132925

Oui, c'est un bon exemple de l'utilité de la fermeture. L'appel à warnUser crée l' calledCount variable dans son champ d'application et retourne une fonction anonyme qui est stocké dans l' warnForTamper variable. Car il y a encore de la fermeture, faisant usage de la calledCount variable, il n'est pas supprimé lors de la fonction de sortie, de sorte que chaque appel à l' warnForTamper() va augmenter la portée de la variable et d'alerte de la valeur.

Le problème le plus commun que je vois sur StackOverflow est où quelqu'un veut de "retarder" l'utilisation d'une variable qui augmente à chaque tour de boucle, mais parce que la variable est définie, alors, chaque référence à la variable serait après la boucle est terminée, entraînant la fin de l'état de la variable:

for (var i = 0; i < someVar.length; i++)
    window.setTimeout(function () { 
        alert("Value of i was "+i+" when this timer was set" )
    }, 10000);

Cela permettrait à chaque alerte en montrant la même valeur de i, la valeur qu'elle a été augmentée à quand la boucle est terminée. La solution est de créer une nouvelle fermeture, une salle de portée de variable. Cela peut être fait à l'aide d'un instantanément exécuté fonction anonyme, qui reçoit la variable et des magasins de son état comme argument:

for (var i = 0; i < someVar.length; i++)
    (function (i) {
        window.setTimeout(function () { 
            alert("Value of i was "+i+" when this timer was set" )
        }, 10000);
    })(i); 

19voto

maerics Points 47743

Dans le JavaScript (ou tout ECMAScript) de la langue, en particulier, les fermetures sont utiles dans la clandestinité la mise en œuvre de la fonctionnalité tout en révélant toujours l'interface.

Par exemple, imaginez que vous écrivez une classe de la date de l'utilitaire de méthodes et que vous souhaitez autoriser les utilisateurs à la recherche de la semaine de noms d'index, mais vous ne voulez pas les voir le tableau des noms que vous utilisez sous le capot.

var dateUtil = {
  weekdayShort: (function() {
    var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    return function(x) {
      if ((x != parseInt(x)) || (x < 1) || (x > 7)) {
        throw new Error("invalid weekday number");
      }
      return days[x - 1];
    };
  }())
};

Notez que l' days tableau pourrait simplement être stockées en tant que propriété de l' dateUtil objet, mais alors il serait visible par les utilisateurs du script et ils pourraient même le changer s'ils le voulaient, sans même avoir besoin de votre code source. Cependant, depuis qu'il est entouré par la fonction anonyme qui renvoie la date de la fonction de recherche il est accessible uniquement par la fonction de recherche de sorte qu'il est désormais inviolable.

8voto

alex Points 186293

Il y a une section sur la Fermeture des pratiques à la Mozilla Developer Network.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X