Les fermetures JavaScript par rapport aux fonctions anonymes

un ami à moi et moi sommes en train de discuter ce qui est une fermeture dans JS et ce qui ne l'est pas. Nous voulons juste être sûrs de bien le comprendre.

prenons cet exemple. Nous avons une boucle de comptage et voulons Imprimer la variable counter sur la console en différé. Par conséquent, nous utilisons setTimeout et fermetures pour capturer la valeur de la variable de compteur pour s'assurer qu'il ne sera pas imprimé N fois la valeur N.

la mauvaise solution sans fermetures ou quelque chose près de fermetures serait:

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

qui imprimera bien sûr 10 fois la valeur de i après la boucle, à savoir 10.

ainsi sa tentative était:

for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i;
        setTimeout(function(){
            console.log(i2);
        }, 1000)
    })();
}

impression de 0 à 9 comme prévu.

je lui ai dit qu'il n'utilise pas fermeture pour capturer i , mais il insiste sur le fait qu'il l'est. J'ai prouvé qu'il n'utilise pas fermetures en plaçant le corps de boucle for Dans un autre setTimeout (passant sa fonction anonyme à setTimeout ), en imprimant 10 fois 10 de nouveau. La même chose s'applique si je stocke sa fonction dans un var et l'exécute après la boucle, aussi l'impression 10 fois 10. Donc mon argument est que il ne fait pas vraiment capture la valeur de i , en faisant sa version pas d'une fermeture.

ma tentative fut:

for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2);
        }
    })(i), 1000);
}

donc je capture i (nommé i2 dans la fermeture), mais maintenant je retourner une autre fonction et passer cela autour. dans mon cas, la fonction passée à setTimeout capture vraiment i .

qui utilise des fermetures et qui ne le fait pas?

notez que les deux solutions impriment 0 à 9 sur la console retardée, donc ils résolvent le problème original, mais nous voulons comprendre laquelle de ces deux solutions utilise des fermetures pour accomplir ceci.

529
demandé sur Azeezah M 2012-10-17 12:36:35

12 réponses

Note de l'Éditeur: Toutes les fonctions en JavaScript sont de fermetures, comme l'explique cette post . Toutefois, nous sommes seulement intéressés à identifier un sous-ensemble de ces fonctions qui sont intéressant d'un point de vue théorique. Dorénavant, toute référence au mot fermeture renvoie à ce sous-ensemble de fonctions, sauf indication contraire.

une explication simple pour les fermetures:

  1. Prendre une fonction. Appelons-le F.
  2. liste de toutes les variables de F.
  3. les variables peuvent être de deux types:
    1. variables locales (variables liées)
    2. variables Non locales (variables libres)
  4. Si F n'a pas de variables libres, alors il ne peut pas être une fermeture.
  5. Si F a une variables (qui sont définies dans a parent portée de F) puis:
    1. il ne doit y avoir qu'une seule portée mère de F à laquelle la variable libre a est liée.
    2. Si F est référencé de l'extérieur que champ parent, alors il devient une fermeture pour que variable libre.
    3. que en franchise la variable est appelée une upvalue de la fermeture F.

maintenant, utilisons ceci pour comprendre qui utilise les fermetures et qui ne le fait pas (pour l'explication j'ai nommé les fonctions):

Case 1: Programme de votre ami

for (var i = 0; i < 10; i++) {
    (function f() {
        var i2 = i;
        setTimeout(function g() {
            console.log(i2);
        }, 1000);
    })();
}

dans le programme ci-dessus il y a deux fonctions: f et g . Voyons s'il s'agit de fermetures:

pour f :

  1. liste des variables:
    1. i2 est une variable locale .
    2. i est une variable free .
    3. setTimeout est une variable free .
    4. g est une variable locale .
    5. console est une variable free .
  2. trouver la portée mère à laquelle chaque variable libre est liée:
    1. i est lié à la portée globale.
    2. setTimeout est lié à la portée globale.
    3. console est lié à la portée globale.
  3. Quelle est la portée de la fonction référencée ? Le de portée mondiale .
    1. donc i n'est pas fermé au-dessus de par f .
    2. donc setTimeout n'est pas fermé au-dessus de par f .
    3. donc console n'est pas fermé au-dessus de par f .

Ainsi, la fonction f n'est pas une fermeture.

pour g :

  1. liste des variables:
    1. console est une variable libre .
    2. i2 est une variable libre .
  2. trouver le domaine d'application parent à que chaque variable libre est liée:
    1. console est lié à la portée globale.
    2. i2 est lié à la portée de la f .
  3. Quelle est la portée de la fonction référencée ? Le champ d'application de setTimeout .
    1. donc console n'est pas fermés par g .
    2. donc i2 est fermé au-dessus de par g .

ainsi la fonction g est une fermeture pour la variable libre i2 (qui est une upvalue pour g ) quand c'est référencé de l'intérieur de setTimeout .

mauvais pour vous: votre ami utilise une fermeture. La fonction interne est une fermeture.

Case 2: Votre Programme

for (var i = 0; i < 10; i++) {
    setTimeout((function f(i2) {
        return function g() {
            console.log(i2);
        };
    })(i), 1000);
}

dans le programme ci-dessus il y a deux fonctions: f et g . Voyons s'il s'agit de fermetures:

pour f :

  1. liste des variables:
    1. i2 est un local à la variable.
    2. g est une variable locale .
    3. console est une variable free .
  2. trouver la portée mère à laquelle chaque variable libre est liée:
    1. console est lié à la portée globale.
  3. Quelle est la portée de la fonction référencée ? Le de portée mondiale .
    1. donc console n'est pas fermé au-dessus de par f .

Ainsi, la fonction f n'est pas une fermeture.

pour g :

  1. liste des variables:
    1. console est une variable free .
    2. i2 est une variable libre .
  2. trouver la portée mère à laquelle chaque variable libre est liée:
    1. console est lié à la portée globale.
    2. i2 est lié à la portée de la f .
  3. Quelle est la portée de la fonction référencée ? Le champ d'application de setTimeout .
    1. donc console n'est pas fermé au-dessus de par g .
    2. donc i2 est fermé au-dessus de par g .

ainsi la fonction g est une fermeture pour la variable libre i2 (qui est une upvalue pour g ) quand c'est référencé de l'intérieur de setTimeout .

Bon pour vous: Vous êtes à l'aide d'une fermeture. La fonction interne est une fermeture.

donc vous et votre ami utilisez des fermetures. Arrêtez de vous battre. J'espère que j'ai effacé le concept de fermetures et comment les identifier pour les deux de vous.

Edit: Une simple explication des raisons pour lesquelles toutes les fonctions sont de fermeture (crédits @Pierre):

considérons D'abord le programme suivant (c'est le control ):

lexicalScope();

function lexicalScope() {
    var message = "This is the control. You should be able to see this message being alerted.";

    regularFunction();

    function regularFunction() {
        alert(eval("message"));
    }
}
  1. nous savons que les deux lexicalScope et regularFunction ne sont pas des fermetures de la définition ci-dessus .
  2. quand nous exécutons le programme nous nous attendons à ce que message soit alerté parce que regularFunction n'est pas une fermeture (i.e. il a accès à tous les variables dans son champ d'application parent - y compris message ).
  3. quand nous exécutons le programme nous observons que message est en effet alerté.

suivant let's considérez le programme suivant (c'est le alternative ):

var closureFunction = lexicalScope();

closureFunction();

function lexicalScope() {
    var message = "This is the alternative. If you see this message being alerted then in means that every function in JavaScript is a closure.";

    return function closureFunction() {
        alert(eval("message"));
    };
}
  1. nous savons que seulement closureFunction est une fermeture de la définition ci-dessus .
  2. quand nous exécutons le programme nous nous attendons à ce que message ne pas être alerté parce que closureFunction est une fermeture (c'est-à-dire qu'il n'a accès qu'à tous les son non-variables locales à la création de la fonction ( voir cette réponse ) - ce n'est pas une message ).
  3. lorsque nous exécutons le programme nous observons que message est effectivement alerté.

Qu'en déduisons-nous?

  1. les interprètes JavaScript ne traitent pas fermetures différemment de la façon dont ils traitent les autres fonctions.
  2. chaque fonction porte avec elle sa scope chain . Les fermetures n'ont pas d'environnement de référence distinct .
  3. une fermeture est comme toutes les autres fonctions. Nous les appelons simplement fermetures quand ils sont référencé dans un champ d'application à l'extérieur le champ d'application auquel ils appartiennent parce que c'est un cas intéressant.
621
répondu Aadit M Shah 2017-05-23 11:47:13

selon la définition de closure :

Une "fermeture" est une expression (généralement une fonction) qui peuvent avoir des variables libres avec une environnement qui lie les variables (qui "ferme" de l'expression).

vous utilisez closure si vous définissez une fonction qui utilise une variable qui est définie en dehors de la fonction. (ce que nous appelons la variable a variable libre ).

Ils utilisent tous closure (même dans le 1er exemple).

91
répondu kev 2012-10-17 09:09:49

en un mot fermetures Javascript permettent une fonction à accéder à une variable qui est déclaré dans une fonction lexicale-parent .

voyons une explication plus détaillée. Pour comprendre les fermetures, il est important de comprendre comment JavaScript scope les variables.

Scopes

dans les portées JavaScript sont définis avec des fonctions. Chaque fonction définit une nouvelle portée.

prenons l'exemple suivant:

function f()
{//begin of scope f
  var foo='hello'; //foo is declared in scope f
  for(var i=0;i<2;i++){//i is declared in scope f
     //the for loop is not a function, therefore we are still in scope f
     var bar = 'Am I accessible?';//bar is declared in scope f
     console.log(foo);
  }
  console.log(i);
  console.log(bar);
}//end of scope f

l'appel de f imprime

hello
hello
2
Am I Accessible?

considérons maintenant le cas où nous avons une fonction g définie dans une autre fonction f .

function f()
{//begin of scope f
  function g()
  {//being of scope g
    /*...*/
  }//end of scope g
  /*...*/
}//end of scope f

nous appellerons f le lexical parent de g . Comme expliqué avant nous avons maintenant 2 portée; la portée f et la portée g .

mais une portée est "dans" l'autre portée, donc la portée de la fonction enfant fait-elle partie de la portée de la fonction parent? Que se passe-t-il avec les variables déclarées dans la portée de la fonction parent; pourrai-je y accéder à partir de la portée de la fonction enfant? C'est exactement là que les fermetures interviennent.

fermetures

In JavaScript la fonction g peut non seulement accéder à toutes les variables déclarées dans le champ d'application g , mais aussi accéder à toutes les variables déclarées dans le champ d'application de la fonction mère f .

Considérez ce qui suit;

function f()//lexical parent function
{//begin of scope f
  var foo='hello'; //foo declared in scope f
  function g()
  {//being of scope g
    var bar='bla'; //bar declared in scope g
    console.log(foo);
  }//end of scope g
  g();
  console.log(bar);
}//end of scope f

l'appel de f imprime

hello
undefined

regardons la ligne console.log(foo); . À ce point nous sommes dans la portée g et nous essayons d'accéder à la variable foo qui est déclaré dans le champ d'application f . Mais comme indiqué avant nous pouvons accéder à n'importe quelle variable déclarée dans une fonction de parent lexical qui est le cas ici; g est le parent lexical de f . C'est pourquoi hello est imprimé.

Regardons maintenant la ligne console.log(bar); . À ce stade, nous sommes dans la portée f et nous essayons d'accéder à la variable bar qui est déclarée dans la portée g . bar n'est pas déclarée dans le champ d'application actuel et le la fonction g n'est pas le parent de f , donc bar est non défini

en fait, nous pouvons également accéder aux variables déclarées dans le cadre d'une fonction lexicale" grand parent". Par conséquent, s'il y aurait une fonction h définie dans la fonction g

function f()
{//begin of scope f
  function g()
  {//being of scope g
    function h()
    {//being of scope h
      /*...*/
    }//end of scope h
    /*...*/
  }//end of scope g
  /*...*/
}//end of scope f

puis h seraient en mesure d'accéder à toutes les variables déclarées dans le champ d'application de la fonction h , g , et f . Cela est fait avec fermetures . En JavaScript fermetures nous permet d'accéder à n'importe quelle variable déclarée dans la fonction lexical parent, dans la fonction lexical grand parent, dans la fonction lexical grand-grand parent, etc. Cela peut être considéré comme une chaîne de portée ; scope of current function -> scope of lexical parent function -> scope of lexical grand parent function -> ... jusqu'à la dernière fonction parent qui n'a pas de parent lexical.

L'objet fenêtre

en fait la chaîne ne s'arrête pas à la dernière fonction parent. Il y a une autre portée spéciale: la portée globale . Chaque variable non déclarée dans une fonction est considérée comme étant déclaré dans la portée globale. La portée globale a deux spécialités;

  • toute variable déclarée dans le champ d'Application global est accessible partout
  • les variables déclarées dans le champ d'Application global correspondent aux propriétés de l'objet window .

il y a donc exactement deux façons de déclarer une variable foo dans la portée globale; soit en ne la déclarant pas dans une fonction, soit en définissant la propriété foo de l'objet fenêtre.

les deux tentatives utilisent des fermetures

Maintenant que vous avez lu une explication plus détaillée il peut maintenant être évident que les deux solutions utilisent des fermetures. Mais pour être sûr, faisons une preuve.

créons un nouveau langage de programmation; JavaScript-No-Closure. Comme son nom l'indique, JavaScript-No-Closure est identique à JavaScript sauf qu'il ne supporte pas les fermetures.

en d'autres termes;

var foo = 'hello';
function f(){console.log(foo)};
f();
//JavaScript-No-Closure prints undefined
//JavaSript prints hello

très bien, voyons ce qui se passe avec la première solution avec JavaScript-No-Closure;

for(var i = 0; i < 10; i++) {
  (function(){
    var i2 = i;
    setTimeout(function(){
        console.log(i2); //i2 is undefined in JavaScript-No-Closure 
    }, 1000)
  })();
}

par conséquent, ce sera imprimé undefined 10 fois en JavaScript-No-Closure.

donc la première solution utilise la fermeture.

regardons la seconde solution;

for(var i = 0; i < 10; i++) {
  setTimeout((function(i2){
    return function() {
        console.log(i2); //i2 is undefined in JavaScript-No-Closure
    }
  })(i), 1000);
}

par conséquent, ce sera imprimé undefined 10 fois en JavaScript-No-Closure.

les deux solutions utilisent des fermetures.

Edit: il est supposé que ces 3 codes les bribes ne sont pas définies dans la portée globale. Dans le cas contraire, les variables foo et i seraient liées à l'objet window et donc accessibles via l'objet window en JavaScript et JavaScript-No-Closure.

46
répondu brillout.com 2013-03-24 18:02:54

Je n'ai jamais été heureux de la façon dont quelqu'un explique cela.

la clé pour comprendre les fermetures est de comprendre ce que serait JS sans fermetures.

sans fermetures, cela lancerait une erreur

function outerFunc(){
    var outerVar = 'an outerFunc var';
    return function(){
        alert(outerVar);
    }
}

outerFunc()(); //returns inner function and fires it

une fois que outerFunc est revenu dans une version JavaScript imaginaire désactivée, la référence à outerVar serait des déchets ramassés et partis ne laissant rien ici pour l'intérieur func pour référence.

Les fermetures

sont essentiellement les règles spéciales qui interviennent et permettent à ces variables d'exister lorsqu'une fonction interne renvoie aux variables d'une fonction externe. Avec les fermetures, les var référencées sont maintenues même après que la fonction externe est terminée ou "fermée" si cela vous aide à vous souvenir du point.

même avec les fermetures, le cycle de vie des voitures locales dans une fonction sans fonctions intérieures qui se réfère à ses habitants fonctionne comme dans une version sans fermeture. Lorsque la fonction est terminée, les habitants de ces ordures.

une fois que vous avez une référence dans une func intérieure à un var extérieur, cependant c'est comme un chambranle de porte est mis dans le chemin de la collecte des ordures pour ces vars référencés.

une façon peut-être plus précise de regarder les fermetures, est que la fonction interne utilise essentiellement la portée interne comme sa propre foudnation de portée.

mais le contexte référencé est en fait, persistant, pas comme un instantané. mise à feu répétée d'une fonction interne retournée qui continue à incrémenter et à enregistrer la var locale d'une fonction externe va continuer à alerter des valeurs plus élevées.

function outerFunc(){
    var incrementMe = 0;
    return function(){ incrementMe++; console.log(incrementMe); }
}
var inc = outerFunc();
inc(); //logs 1
inc(); //logs 2
19
répondu Erik Reppen 2015-07-06 15:29:52

vous utilisez tous les deux des fermetures.

je vais avec le définition Wikipedia ici:

en informatique, une fermeture (également une fermeture ou une fonction lexicale) la fermeture est une fonction ou une référence à une fonction avec un environnement de référence-un tableau stockant une référence à chacun des variables non locales (également appelées variables libres) de cette fonction. Une fermeture-contrairement à une simple fonction pointeur-permet à une fonction d'accéder ces variables non locales, même lorsqu'elles sont invoquées en dehors de leur contexte immédiat portée lexicale.

la tentative de votre ami utilise clairement la variable i , qui n'est pas locale, en prenant sa valeur et en faisant une copie pour stocker dans le local i2 .

votre propre tentative passe i (qui au site d'appel est dans la portée) à une fonction anonyme comme un argument. Ce n'est pas une fermeture jusqu'à présent, mais ensuite cette fonction renvoie une autre fonction qui renvoie la même i2 . Comme à l'intérieur de la fonction anonyme interne i2 n'est pas un local, cela crée une fermeture.

16
répondu Jon 2012-10-17 09:08:52

vous et votre ami utilisez tous les deux des fermetures:

une fermeture est un type particulier d'objet qui combine deux choses: une fonction, et l'environnement dans lequel cette fonction a été créée. L'environnement est constitué de toutes les variables locales qui étaient présentes au moment où la fermeture a été créée.

MDN: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures

dans la fonction de code de votre ami function(){ console.log(i2); } défini à l'intérieur de la fermeture de la fonction anonyme function(){ var i2 = i; ... et peut lire / écrire la variable locale i2 .

dans votre fonction de code function(){ console.log(i2); } défini à l'intérieur fermeture de la fonction function(i2){ return ... et peut lire / écrire valeur locale i2 (déclaré dans ce cas comme paramètre).

dans les deux cas Fonction function(){ console.log(i2); } alors passé en setTimeout .

un autre équivalent (mais avec moins d'utilisation de la mémoire) est:

function fGenerator(i2){
    return function(){
        console.log(i2);
    }
}
for(var i = 0; i < 10; i++) {
    setTimeout(fGenerator(i), 1000);
}
12
répondu Andrew D. 2012-10-24 16:51:51

fermeture

une fermeture n'est pas une fonction, ni une expression. Il doit être considéré comme une sorte de "snapshot" à partir des variables utilisées en dehors du champ de fonctions et utilisées à l'intérieur de la fonction. Grammaticalement, on devrait dire: "prenez la fermeture de la variable.

Encore une fois, en d'autres termes: Une fermeture est une copie du contexte de variables sur lesquelles la fonction dépend.

une fois de plus (naïf): Une fermeture est d'avoir accès à des variables qui ne sont pas passé comme paramètre.

gardez à l'esprit que ces concepts fonctionnels dépendent fortement du langage / environnement de programmation que vous utilisez. En JavaScript, la fermeture dépend de la portée lexicale (ce qui est vrai dans la plupart des langues c).

donc, retourner une fonction revient le plus souvent à retourner une fonction anonyme / sans nom. Lorsque les variables d'accès de la fonction, pas passé comme paramètre, et à l'intérieur sa portée (lexicale), une clôture a été prise.

donc, concernant vos exemples:

// 1
for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i); // closure, only when loop finishes within 1000 ms,
    }, 1000);           // i = 10 for all functions
}
// 2
for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i; // closure of i (lexical scope: for-loop)
        setTimeout(function(){
            console.log(i2); // closure of i2 (lexical scope:outer function)
        }, 1000)
    })();
}
// 3
for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2); // closure of i2 (outer scope)

        }
    })(i), 1000); // param access i (no closure)
}

tous utilisent des fermetures. Ne confondez pas le point d'exécution avec les fermetures. Si l' "instantané" des fermetures est pris au mauvais moment, les valeurs peuvent être inattendues, mais certainement une fermeture est prise!

9
répondu Andries 2012-10-17 10:35:32

regardons dans les deux sens:

(function(){
    var i2 = i;
    setTimeout(function(){
        console.log(i2);
    }, 1000)
})();

déclare et exécute immédiatement une fonction anonyme qui exécute setTimeout() dans son propre contexte. La valeur actuelle de i est conservée en faisant une copie dans i2 d'abord; cela fonctionne en raison de l'exécution immédiate.

setTimeout((function(i2){
    return function() {
        console.log(i2);
    }
})(i), 1000);

déclare un contexte d'exécution pour la fonction interne par lequel la valeur actuelle de i est conservée dans i2 ; cette approche utilise également l'exécution immédiate pour préserver la valeur.

Important

il faut mentionner que la sémantique de run N'est pas la même entre les deux approches; votre fonction interne passe à setTimeout() alors que sa fonction interne appelle setTimeout() elle-même.

envelopper les deux codes dans un autre setTimeout() ne prouve pas que seule la seconde approche utilise des fermetures, il n'y a tout simplement pas la même chose pour commencer.

Conclusion

les deux méthodes utilisent des fermetures, de sorte qu'il se résume à un goût personnel; la deuxième approche est plus facile de" se déplacer " ou de généraliser.

9
répondu Ja͢ck 2012-10-17 11:28:24

j'ai écrit ceci il y a un certain temps pour me rappeler ce qu'est une fermeture et comment elle fonctionne dans JS.

Une fermeture est une fonction qui, lorsqu'elle est appelée, utilise l'étendue dans laquelle elle a été déclarée, et non pas le domaine dans lequel il a été appelé. Dans javaScript, toutes les fonctions se comportent comme ceci. Les valeurs variables dans une portée persistent tant qu'il y a une fonction qui les indique. L'exception à la règle est "il", qui se réfère à l'objet sur lequel la fonction est à l'intérieur lorsqu'il est appelé.

var z = 1;
function x(){
    var z = 2; 
    y(function(){
      alert(z);
    });
}
function y(f){
    var z = 3;
    f();
}
x(); //alerts '2' 
7
répondu Nat Darke 2012-12-21 19:10:29

après une inspection minutieuse, on dirait que vous utilisez la fermeture.

dans le cas de votre ami, i est accessible à l'intérieur de la fonction anonyme 1 et i2 est accessible à l'intérieur de la fonction anonyme 2 où le console.log est présent.

dans votre cas, vous accédez à i2 dans la fonction anonyme où console.log est présent. Ajouter une déclaration debugger; avant console.log et dans les outils de développement chrome sous " Scope variables" indique la portée de la variable.

5
répondu Ramesh 2012-10-17 09:07:59

considérez ce qui suit. Cela crée et recrée une fonction f qui se ferme sur i , mais des fonctions différentes!:

i=100;

f=function(i){return function(){return ++i}}(0);
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));

f=function(i){return new Function('return ++i')}(0);        /*  function declarations ~= expressions! */
alert([f,f(),f(),f(),f(),f(),f(),f(),f(),f(),f()].join('\n\n'));

alors que ce qui suit se ferme sur "une" fonction "elle-même "

( eux-mêmes! l'extrait suivant utilise un seul référent f )

for(var i = 0; i < 10; i++) {
    setTimeout( new Function('console.log('+i+')'),  1000 );
}

ou, pour être plus explicite:

for(var i = 0; i < 10; i++) {
    console.log(    f = new Function( 'console.log('+i+')' )    );
    setTimeout( f,  1000 );
}

NB. la dernière définition de f est function(){ console.log(9) } avant 0 est imprimée.

mise en garde! La fermeture concept peut être une contrainte à la distraction de l'essence de la programmation élémentaire:

for(var i = 0; i < 10; i++) {     setTimeout( 'console.log('+i+')',  1000 );      }

x-réf.:

comment fonctionnent les fermetures JavaScript?

Explication Des Fermetures Javascript

est-ce qu'une fermeture (JS) nécessite une fonction à l'intérieur d'une fonction

comment comprendre les fermetures en Javascript?

Javascript variable locale et globale confusion

3
répondu ekim 2017-05-23 12:10:07

j'aimerais partager mon exemple et une explication au sujet des fermetures. J'ai fait un exemple python, et deux figures pour montrer les états de la pile.

def maker(a, b, n):
    margin_top = 2
    padding = 4
    def message(msg):
        print('\n’ * margin_top, a * n, 
            ' ‘ * padding, msg, ' ‘ * padding, b * n)
    return message

f = maker('*', '#', 5)
g = maker('', '♥’, 3)
…
f('hello')
g(‘good bye!')

La sortie de ce code serait comme suit:

*****      hello      #####

      good bye!    ♥♥♥

voici deux figures pour montrer les piles et la fermeture attachée à l'objet de fonction.

lorsque la fonction est retournée par le fabricant

lorsque la fonction est appelée plus tard

lorsque la fonction est appelée à travers un paramètre ou une variable non locale, le code a besoin de liaisons de variables locales telles que margin_top, padding ainsi que a, b, N. Afin de s'assurer que le code de fonction fonctionne, le cadre de pile de la fonction maker qui a disparu il y a longtemps devrait être accessible, ce qui est sauvegardé dans la fermeture que nous pouvons trouver avec l'objet de message de fonction.

0
répondu Eunjung Lee 2018-05-12 03:45:42