Comment fonctionnent les bloqueurs javascript?

Comment expliqueriez-vous la fermeture de JavaScript pour une personne ayant une connaissance des concepts qui le composent (par exemple, des fonctions, des variables, etc.) sans comprendre les fermetures elles-mêmes?

J'ai vu un exemple du plan donné dans Wikipedia, mais, malheureusement, cela n'a pas aidé.

7654
21 сент. réglé sur e-satis le 21 sept. 2008-09-21 17:12 08 à 17h12 2008-09-21 17:12
@ 89 réponses
  • 1
  • 2
  • 3

Fermeture de javascript pour les débutants

Soumis par Morris le mar, 2006-02-21 10:19. La communauté a été modifiée depuis.

Fermer n'est pas magique

Cette page explique la fermeture pour que le programmeur puisse les comprendre - en utilisant du code JavaScript fonctionnel. Ce n'est pas pour les gourous ou les programmeurs fonctionnels.

La fermeture n’est pas difficile à comprendre dès que le concept de base est cousu. Cependant, ils ne peuvent pas être compris en lisant des explications théoriques ou académiques!

Cet article est destiné aux programmeurs possédant une expérience de base en programmation et pouvant lire la fonction JavaScript suivante:

première classe .  est une expression qui peut faire référence à des variables comprises dans sa portée (lorsqu’elle a déjà été déclarée), être affectée à une variable, passée en tant qu’argument de fonction ou renvoyée comme résultat d’une fonction. 

Exemple de clôture

Le code suivant renvoie une référence de fonction:

 function say667() { // Local variable that ends up within closure var num = 42; var say = function() { console.log(num); } num++; return say; } var sayNumber = say667(); sayNumber(); // logs 43 

Exemple 4

Les trois fonctions globales ont une référence commune à la même fermeture, car elles sont toutes déclarées lors d'un seul appel à setupSomeGlobals() .

 function sayAlice() { var say = function() { console.log(alice); } // Local variable that ends up within closure var alice = 'Hello Alice'; return say; } sayAlice()();// logs "Hello Alice" 

Tricky: notez également say variable say est également à l'intérieur de la fermeture et qu'elle peut dire à sayAlice() toute autre fonction pouvant être déclarée dans sayAlice() , ou qu'elle peut être obtenue de manière récursive dans une fonction interne.

Exemple 6

C'est une vraie magie pour tout le monde, vous devez donc le comprendre. Soyez très prudent si vous définissez une fonction dans une boucle: les variables locales de la fermeture peuvent ne pas agir comme vous le pensiez.

Vous devez comprendre la fonction "variable de levage" de javascript pour comprendre cet exemple.

 function newClosure(someNum, someRef) { // Local variables that end up within closure var num = someNum; var anArray = [1,2,3]; var ref = someRef; return function(x) { num += x; anArray.push(num); console.log('num: ' + num + '; anArray: ' + anArray.toString() + '; ref.someVar: ' + ref.someVar + ';'); } } obj = {someVar: 4}; fn1 = newClosure(4, obj); fn2 = newClosure(5, obj); fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4; fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4; obj.someVar++; fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5; fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5; 

Résumé

Si tout semble complètement flou, il est préférable de jouer avec des exemples. Lire des explications est beaucoup plus difficile que de comprendre des exemples. Mes explications sur les fermetures et les cadres de pile, etc. Ils ne sont pas techniquement corrects - ce sont des simplifications grossières conçues pour aider à comprendre. Une fois l’idée de base résolue, vous pourrez obtenir les détails ultérieurement.

Points finaux:

  • Chaque fois que vous utilisez la function dans une autre fonction, la fermeture est utilisée.
  • Chaque fois que vous utilisez eval() dans une fonction, une clôture est utilisée. Le texte que vous eval peut faire référence aux variables locales d'une fonction et vous pouvez même créer de nouvelles variables locales avec eval('var foo = …')
  • Lorsque vous utilisez une new Function(…) ( constructeur de fonctions ) dans une fonction, elle ne crée pas de fermeture. (La nouvelle fonction ne peut pas faire référence aux variables locales de la fonction externe.)
  • Fermer en JavaScript revient à conserver une copie de toutes les variables locales, comme lorsque vous quittez une fonction.
  • Il est probablement préférable de penser que la fermeture est toujours créée en tant qu'entrée de fonction et que des variables locales sont ajoutées à cette fermeture.
  • Un nouvel ensemble de variables locales est enregistré chaque fois qu'une fonction est appelée avec une fermeture (étant donné que la fonction contient une déclaration de fonction, ou que la référence à cette fonction interne est renvoyée ou que la référence externe est stockée pour elle d'une manière ou d'une autre).
  • Deux fonctions peuvent sembler avoir le même code source, mais avoir un comportement complètement différent en raison de leur fermeture cachée. Je ne pense pas que le code JavaScript puisse vraiment savoir si la fonction a une fermeture de lien ou non.
  • Si vous essayez d’apporter des modifications au code source dynamique (par exemple: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola')); ), cela ne fonctionnera pas si myFunction est une fermeture (bien sûr, vous vous ne songez pas à remplacer les lignes source au moment de l'exécution, mais ...).
  • Vous pouvez obtenir les déclarations de fonction dans les déclarations de fonction dans les fonctions mdash, et vous pouvez obtenir une clôture à plusieurs niveaux.
  • Je pense que la clôture est généralement un terme à la fois pour une fonction et pour des variables capturées. Veuillez noter que je n'utilise pas cette définition dans cet article!
  • Je soupçonne que les fermetures en JavaScript sont différentes de celles que l'on trouve couramment dans les >

les connexions

grâce à

Si vous venez tout juste d’apprendre la fermeture (ici ou ailleurs!), Je souhaiterais connaître votre avis sur les modifications que vous pourriez suggérer pour rendre cet article plus clair. Envoyer un message à morrisjohns.com (morris_closure @). S'il vous plaît noter que je ne suis pas un gourou JavaScript - pas à la fin.


Le message original de Morris peut être trouvé dans les archives Internet .

6329
21 сент. la réponse est donnée par Joel Anair 21 sep . 2008-09-21 17:18 '08 à 17:18 2008-09-21 17:18

Chaque fois que vous voyez le mot-clé de fonction dans une autre fonction, la fonction interne a accès aux variables de la fonction externe.

 function foo(x) { var tmp = 3; return function (y) { console.log(x + y + (++tmp)); // will also log 16 } } var bar = foo(2); // bar is now a closure. bar(10); 

La fonction ci-dessus écrira également 16, car bar peut toujours se référer à x et tmp , même s'il ne fait plus partie de la région.

Cependant, étant donné que tmp reste suspendu autour de la fermeture de la bar intérieure, il augmente également. Il augmentera chaque fois que vous appelez la bar .

L'exemple le plus simple d'une fermeture est le suivant:

border=0

 function foo(x) { var tmp = 3; return function (y) { console.log(x + y + tmp); x.memb = x.memb ? x.memb + 1 : 1; console.log(x.memb); } } var age = new Number(2); var bar = foo(age); // bar is now a closure referencing age. bar(10); 

Comme prévu, chaque appel à la bar(10) incrémentera x.memb . Vous ne pouvez pas vous attendre x ce que x réfère simplement au même objet que la variable age ! Après quelques appels au bar age.memb aura 2! Ce lien sert de base aux fuites de mémoire avec les objets HTML.

3825
21 сент. réponse donnée à Ali le 21 septembre. 2008-09-21 18:16 2008 à 18h16 2008-09-21 18:16

AVANT-PROPOS: cette réponse a été écrite alors que la question était:

Comme le vieil Albert, il a déclaré: "Si vous ne pouvez pas expliquer cela à un enfant de six ans, vous ne comprenez pas vous-même." Eh bien, j’ai essayé d’expliquer la fermeture de JS à un ami de 27 ans et j’ai complètement échoué.

Quelqu'un pourrait-il penser que je suis âgé de 6 ans et étrangement intéressé par cette question?

Je suis à peu près sûr d'être l'un de ceux qui ont tenté de prendre la question initiale à la lettre. Depuis lors, cette question a été mutée plusieurs fois et ma réponse peut maintenant sembler incroyablement stupide et inappropriée. J'espère que l'idée générale de cette histoire reste pour certains intéressante.


J'aime beaucoup les analogies et les métaphores pour expliquer des concepts complexes, alors laissez-moi m'essayer à l'histoire.

Il était une fois:

Il y avait une princesse ...

 function princess() { 

Elle a vécu dans un monde merveilleux rempli d'aventures. Elle a rencontré son prince Charles, a parcouru son monde en licorne, s'est battue avec des dragons, a rencontré des animaux qui parlent et de nombreuses autres choses fantastiques.

  var adventures = []; function princeCharming() {  } var unicorn = {  }, dragons = [  ], squirrel = "Hello!";  

Mais elle devait toujours retourner dans son monde ennuyeux d'ennuis et d'adultes.

  return { 

Et elle leur racontait souvent sa dernière aventure incroyable en tant que princesse.

  story: function() { return adventures[adventures.length - 1]; } }; } 

Mais tout ce qu'ils ont vu était une petite fille ...

 var littleGirl = princess(); 

... raconter des histoires de magie et de fantaisie.

 littleGirl.story(); 

Et tandis que les adultes connaissaient de vraies princesses, ils n'auraient jamais cru aux licornes ni aux dragons, car ils ne les avaient jamais vues. Les adultes ont dit qu'ils n'existent que dans l'imagination d'une petite fille.

Mais nous connaissons la vraie vérité. qu'une petite fille avec une princesse à l'intérieur ...

... En fait une princesse avec une petite fille à l'intérieur.

2273
24 июня '11 в 21:49 2011-06-24 21:49 la réponse est donnée par Jacob Swartwood le 24 juin '11 à 21:49 2011-06-24 21:49

Si nous prenons cette question au sérieux, nous devons découvrir qu’une personne typique de six ans a des capacités cognitives, bien que ceux qui s’intéressent à JavaScript ne soient pas aussi typiques.

Sur le développement de l'enfance: de 5 à 7 ans on dit:

Votre enfant sera capable de suivre des instructions en deux étapes. Par exemple, si vous dites à votre enfant: "Va à la cuisine et prends un sac poubelle", ils peuvent se rappeler cette direction.

Nous pouvons utiliser cet exemple pour expliquer les fermetures comme suit:

Une cuisine est une fermeture dans laquelle se trouve une variable locale appelée trashBags . Dans la cuisine, il existe une fonction getTrashBag qui reçoit un sac à ordures et le renvoie.

Nous pouvons l'encoder en javascript comme suit:

696
02 сент. la réponse est donnée dlaliberte 02 sep . 2011-09-02 18:23 '11 à 18:23 2011-09-02 18:23

Homme de paille

J'ai besoin de savoir combien de fois le bouton est enfoncé et de faire quelque chose à chaque troisième clic ...

Solution assez évidente

 <button id="button">Click Me!</button> 

Cela fonctionnera maintenant, mais envahira la zone externe en ajoutant une variable dont le seul but est de suivre le compte. В некоторых ситуациях это было бы предпочтительнее, так как вашему внешнему приложению может потребоваться доступ к этой информации. Но в этом случае мы меняем только каждый третий клик, поэтому рекомендуется включать эту функциональность внутри обработчика событий .

Рассмотрим этот вариант

 <button id="button">Click Me!</button>