Question
Code A
function fun(n,o){ console.log(o); return { fun:function(m){//[2] return fun(m,n);//[1] } } } var a=fun(0); a.fun(1); a.fun(2); a.fun(3); var b=fun(0).fun(1).fun(2).fun(3); var c=fun(0).fun(1); c.fun(2); c.fun(3);
Trouver la sortie du programme
Ceci est une question de test de clôture
Convertir en code équivalent
L'attribut fun de l'objet renvoyé par return correspond à un objet fonction nouvellement créé. Cet objet fonction formera une portée de fermeture, lui permettant d'accéder à la variable n de la fonction externe et à la fonction externe fun. combiner la fonction fun avec L'attribut fun est confus, on modifie le code ci-dessus comme suit :
Code B
function _fun_(n,o){ console.log(o); return { fun:function(m){ return _fun_(m,n); } } } var a=_fun_(0);//undefined a.fun(1);//0 a.fun(2);//0 a.fun(3);//0 var b=_fun_(0).fun(1).fun(2).fun(3); //undefined,0,1,2 var c=fun(0).fun(1);//undefined,0, c.fun(2);//1 c.fun(3); //1
Ensuite, certains étudiants ont demandé, pourquoi cela peut-il être modifié comme ça ? Comment pouvez-vous être sûr que le plaisir en [1] n'est pas le plaisir en [2] où se trouve le code ? Vous devez savoir que l'attribut fun ici ? pointe vers un objet fonction ~
Nous parlons ici de la portée lexicale de JS. La portée de la variable JS existe dans le corps de la fonction, c'est-à-dire le corps de la fonction, et la portée de la variable est déterminée lorsque la définition de la fonction est déclarée, et non lorsque la fonction est exécutée.
Le code suivant
var name="global"; function foo(){ console.log(name); } function fooOuter1(){ var name="local"; foo(); } fooOuter1();//输出global 而不是local,并且和闭包没有任何关系 function fooOuter2(){ var name="local"; function foo(){ console.log(name); } foo(); } fooOuter2();//输出local 而不是global,在函数声明是name变量作用域就在其外层函数中,嗯嗯就是闭包~<br />
D'accord, revenons au sujet. Dans l'étape de définition de la déclaration de fonction, la fonction anonyme en [2] est définie et déclarée qu'un objet fonction nommé fun doit être référencé en [1]. recherchez-le d'abord dans le corps de la fonction actuelle. Si vous trouvez qu'il n'est pas trouvé, accédez à sa fonction externe - la fonction d'emballage de cette fonction anonyme pour rechercher, et vous constatez qu'il n'est pas trouvé. Accédez à la fonction externe et. trouvez qu'il n'y a pas de wrapper de fonction à l'extérieur, puis allez dans l'environnement global pour le trouver, hein. Je l'ai enfin trouvé... Spécifiez simplement la fonction fun comme objet de fonction fun dans l'environnement global et ajoutez-la à la fermeture de l'anonyme. fonction. À ce stade, nous savons pourquoi le code B est équivalent au code A~~~
Créer une portée de fermeture
Après l'analyse lexicale, JS détermine une fermeture, qui est la fermeture de la fonction anonyme correspondant à l'attribut fun de l'objet renvoyé - la fonction variable interne n qui accède à _func_ dans l'environnement global et sa fonction externe <🎜 ; >
Chaque fois que _func_ est exécuté, les informations de portée des variables dans la fermeture seront transmises à l'environnement d'exécution de la fonction pour être utilisées lors de l'obtention de la valeur de la variable lorsque la fonction est exécutée
var a=_fun_(0);//undefined a.fun(1);//0 a.fun(2);//0 a.fun(3);//0
a.fun(1) exécute la méthode fun de l'objet renvoyé, transmet la valeur de m 1 et l'appel renvoie _fun_(1,0)
La sortie est donc 0, a.fun(2), a.fun(3) et a.fun(1)
var b=_fun_(0).fun(1).fun(2).fun(3);
Code équivalent :
var b=_fun_(0);
var b1=b.fun(1);
var b2=b1.fun(2);//[3]
var b3=b2.fun(3);//[4]
Les deux premières phrases sont identiques à la sortie ci-dessus undefined,0 Lorsque [3] est appelé, il y a une fermeture dans l'objet b1, qui fait référence à la fonction _fun_ et à la variable de fonction externe n=1. , donc L'appel de fonction effectué par la fonction anonyme est _fun_(2,1), le résultat de sortie est 1 et un nouvel objet est renvoyé.
Lorsque [4] est exécuté, l'objet b2 a également une fermeture, qui fait référence à la fonction _fun_ et à la variable de fonction externe n=2. Lorsque _fun_(3,2) est exécuté, le résultat de sortie est 2
.
var c=fun(0).fun(1);//undefined,0, c.fun(2);//1 c.fun(3); //1