Heim > Artikel > Web-Frontend > JS Core Series: Eine kurze Diskussion zum Funktionsumfang
1. Geltungsbereich
Der sogenannte Geltungsbereich ist: Variablen werden im Funktionskörper definiert, in dem sie deklariert sind, und in jedem Funktionskörper, in dem dieser Funktionskörper verschachtelt ist.
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) Auf die in der Scope-Funktion definierte Variable foo kann nicht nur allein zugegriffen werden, sondern auch in if-Anweisungen, while-Anweisungen und eingebetteten anonymen Funktionen. Daher ist der Gültigkeitsbereich von foo der Funktionskörper des Gültigkeitsbereichs.
(2) In JavaScript können if, while, for und andere Codeblöcke keine unabhängigen Bereiche bilden. Daher gibt es in JavaScript keinen Bereich auf Blockebene, sondern nur einen Funktionsbereich.
Allerdings gibt es in JS einen Sonderfall:
Wenn eine Variable nicht mit var deklariert wird, hat window dieses Attribut, also Der Gültigkeitsbereich dieser Variablen gehört nicht zu einem bestimmten Funktionskörper, sondern zum Fensterobjekt.
function varscope(){ foo = "I'm in function"; console.log(foo);//I'm in function } varscope(); console.log(window.foo); //I'm in function
2. Scope Chain (Scope Chain)
Die sogenannte Scope Chain ist: Es gibt mehrere Schichten von Funktionskörpern, die in einem Funktionskörper verschachtelt sind, und dieselbe Variable ist in verschiedenen Funktionskörpern definiert. Wenn eine der Funktionen auf diese Variable zugreift, wird eine Bereichskette gebildet. Wenn
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, platziert die JS-Engine den Bereich „Second“ an der Spitze der verknüpften Liste, gefolgt vom Bereich „First“ und schließlich dem Fensterobjekt, sodass die folgende Bereichskette gebildet wird :
second->first->window, zu diesem Zeitpunkt sucht die JS-Engine nach der Variablen foo entlang der Bereichskette, und was gefunden wird, ist „second“
Wenn drittes ausgeführt wird, wird der durch die dritte Kette gebildete Bereich: Third->first->window, also wird Folgendes gefunden: „frist“
Sonderfall: mit Anweisung
Die with-Anweisung in JS wird hauptsächlich verwendet, um die Bereichskette vorübergehend zu erweitern und die Objekte in der Anweisung zum Kopf des Bereichs hinzuzufügen. Nach Beendigung der with-Anweisung kehrt die Gültigkeitsbereichskette zum Normalzustand zurück.
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();
Beim Ausführen von Third() wird ein obj-Objekt übergeben, und obj hat das Attribut foo. Beim Ausführen der with-Anweisung platziert die JS-Engine obj an der Spitze der ursprünglichen verknüpften Liste und bildet so Die Gültigkeitsbereichskette lautet wie folgt:
obj->third->first->window Das zu diesem Zeitpunkt gefundene foo ist das foo in obj, daher lautet die Ausgabe: „obj“ vor with Anschließend wird die Suche entlang der ursprünglichen verknüpften Liste durchgeführt. Dies zeigt, dass die Bereichskette nach Beendigung der with-Anweisung wieder normal ist.
3. Dieses Schlüsselwort
In einer Funktion ist dies immer der Fall zeigt auf das Eigentümerobjekt der aktuellen Funktion dies kann nur seinen spezifischen Zeiger und sein aufrufendes Objekt zur Laufzeit ermitteln.
Dieser Satz fasst alles zusammen: Merken, Merken, Merken! (Ps: Sagen Sie wichtige Dinge dreimal!)
window.name = "window"; function f(){ console.log(this.name); } f();//window var obj = {name:'obj'}; f.call(obj); //obj
Wenn f() ausgeführt wird, ist der Aufrufer von f() das Fensterobjekt. Die Ausgabe von „window“
f.call(obj) bedeutet also, dass f() in das Objekt ausgeführt wird Objekt, das zu obj.f() entspricht. Zu diesem Zeitpunkt ist dies in f obj, daher ist die Ausgabe „obj“
4. Tatsächlich Kampfanwendung
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 und Code2 sind hierfür am besten geeignet und Umfang Gute Zusammenfassung Wenn Sie Zweifel an den Laufergebnissen haben, können Sie diese gerne besprechen!
Code-Analyse:
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"