Maison > Article > interface Web > JS Core Series : une brève discussion sur la portée des fonctions
1. Portée
La soi-disant portée est la suivante : les variables sont définies dans le corps de la fonction dans lequel elles sont déclarées et dans tout corps de fonction dans lequel ce corps de fonction est imbriqué.
function scope(){ var foo = "global"; if(window.getComputedStyle){ var a = "I'm if"; console.log("if:"+foo); //if:global } while(1){ var b = "I'm while"; console.log("while:"+foo);//while:global break; } !function (){ var c = "I'm function"; console.log("function:"+foo);//function:global }(); console.log( foo,//global a, // I'm if b, // I'm while c // c is not defined ); } scope();
(1) En plus d'être accessible par elle-même, la variable foo définie dans la fonction scope est également accessible dans les instructions if, while et les fonctions anonymes intégrées. Par conséquent, la portée de foo est le corps de la fonction scope.
(2) En JavaScript, if, while, for et d'autres blocs de code ne peuvent pas former de portées indépendantes. Par conséquent, il n’y a pas de portée au niveau du bloc en JavaScript, seulement une portée de fonction.
Cependant, il existe un cas particulier en JS :
Si une variable n'est pas déclarée à l'aide de var, window aura cet attribut, donc La portée de cette variable n'appartient pas à un certain corps de fonction, mais à l'objet window.
function varscope(){ foo = "I'm in function"; console.log(foo);//I'm in function } varscope(); console.log(window.foo); //I'm in function
2. Chaîne de portée (chaîne de portée)
La soi-disant chaîne de portée est : un corps de fonction comporte plusieurs couches de corps de fonction imbriquées en son sein, et la même variable est définie dans différents corps de fonction. Lorsqu'une des fonctions accède à cette variable, une chaîne de portée est formée. Lorsque
foo = "window"; function first(){ var foo = "first"; function second(){ var foo = "second"; console.log(foo); } function third(){ console.log(foo); } second(); //second third(); //first } first();
ond, le moteur JS placera la portée de second en tête de la liste chaînée, suivi de la portée de premier, et enfin de l'objet fenêtre, ainsi la chaîne de portée suivante sera formée :
second->first->window, à ce moment, le moteur JS recherche la variable foo le long de la chaîne de portée, et ce qui est trouvé est "second"
Quand troisième est exécuté, la portée formée par la troisième chaîne : troisième->première->fenêtre, donc ce qui est trouvé est : "premier"
Cas particulier : avec instruction
L'instruction with dans JS est principalement utilisée pour étendre temporairement la chaîne de portée et ajouter les objets de l'instruction en tête de la portée. Une fois l’instruction with terminée, la chaîne de portée revient à la normale.
foo = "window"; function first(){ var foo = "first"; function second(){ var foo = "second"; console.log(foo); } function third(obj){ console.log(foo); //first with (obj){ console.log(foo); //obj } console.log(foo); //first } var obj = {foo:'obj'}; third(obj); } first();
Lors de l'exécution de Third(), un objet obj est passé et obj a l'attribut foo Lors de l'exécution de l'instruction with, le moteur JS place obj en tête de la liste chaînée d'origine, formant ainsi. La chaîne de portée est la suivante :
obj->third->first->window. Le foo trouvé à ce moment est le foo dans obj, donc la sortie est : "obj", avant with. et ensuite, la recherche est effectuée le long de la liste chaînée d'origine, ce qui montre qu'après la fin de l'instruction with, la chaîne de portée est revenue à la normale.
3. ce mot clé
Dans une fonction, cela C'est toujours pointe vers l'objet propriétaire de la fonction actuelle. this ne peut déterminer que son pointeur spécifique et son objet appelant au moment de l'exécution.
Cette phrase résume tout à ce sujet, souviens-toi, souviens-toi, souviens-toi ! (ps : Dites les choses importantes trois fois !)
window.name = "window"; function f(){ console.log(this.name); } f();//window var obj = {name:'obj'}; f.call(obj); //obj
Lorsque f() est exécuté, l'appelant de f() est l'objet window, donc afficher "window"
f.call(obj) signifie mettre f() dans Executed sur l'objet obj , ce qui équivaut à obj.f(). À l'heure actuelle, ceci dans f est obj, donc la sortie est "obj"
4. Combat réel Application
code1 :
var foo = "window"; var obj = { foo : "obj", getFoo : function(){ return function(){ return this.foo; }; } }; var f = obj.getFoo(); f(); //window
code2 :
var foo = "window"; var obj = { foo : "obj", getFoo : function(){ var that = this; return function(){ return that.foo; }; } }; var f = obj.getFoo(); f(); //obj
code1 et code2 sont les meilleurs pour cela et portée Bon résumé. Si vous avez des doutes sur les résultats en cours, n'hésitez pas à en discuter !
Analyse du code :
code1: 执行var f = obj.getFoo()返回的是一个匿名函数,相当于: var f = function(){ return this.foo; } f() 相当于window.f(), 因此f中的this指向的是window对象,this.foo相当于window.foo, 所以f()返回"window" code2: 执行var f = obj.getFoo() 同样返回匿名函数,即: var f = function(){ return that.foo; } 唯一不同的是f中的this变成了that, 要知道that是哪个对象之前,先确定f的作用域链:f->getFoo->window 并在该链条上查找that,此时可以发现that指代的是getFoo中的this, getFoo中的this指向其运行时的调用者,从var f = obj.getFoo() 可知此时this指向的是obj对象,因此that.foo 就相当于obj.foo,所以f()返回"obj"