Heim  >  Artikel  >  Web-Frontend  >  JavaScript-Bereich und dieses Schlüsselwort

JavaScript-Bereich und dieses Schlüsselwort

高洛峰
高洛峰Original
2016-11-28 14:14:441156Durchsuche

Als Programmierer sind Sie möglicherweise an Referenzen (oder Zeiger) gewöhnt, die in objektorientierten Sprachen auf das aktuelle Objekt verweisen, wie z. B. this in C++ oder self in Python, die natürlich OO-Attribute haben (Javascript ist es eigentlich). mehr JavaScript, eine sogenannte funktionale Sprache, verfügt auch über einen Zeiger (oder eine Referenz), der auf das Objekt der aktuellen Eigenschaft verweist, nämlich das Schlüsselwort this.

Wenn Sie sich nur einen Satz merken möchten, um dieses Schlüsselwort zu verstehen, sollte dieses Schlüsselwort immer auf das Eigentümerobjekt (Ausführungsraum) der aktuellen Funktion verweisen. Wie ist dieser Satz zu verstehen? Weitere Informationen finden Sie unten in den detaillierten Anweisungen.

Was ist also der Umfang?

Die Erklärung in Wikipedia lautet: In der Computerprogrammierung ist der Umfang ein umschließender Kontext, in dem Werte und Ausdrücke verknüpft sind. Chinesisch ist der sogenannte Bereich, der den Kontext (Ausführungsraum, auf den verwiesen werden kann) angibt, der einem Wert oder Ausdruck zugeordnet ist.

Was hat Scope damit zu tun? Aus der obigen Definition geht hervor, dass dies immer auf das Objekt verweist, das aktuell auf diese Funktion verweist. Wenn Sie das aktuell referenzierte Objekt ermitteln möchten, müssen Sie den Umfang der aktuellen Funktion ermitteln. Einzelheiten finden Sie in der Analyse unten.

dieses Schlüsselwort

Bitte sehen Sie sich unten einige Beispiele an.

Ein Python-Beispiel:

class Person(object):
"""a person class
    """
def __init__(self, name):
self.name = name    #这里的self指向的是实例化后的对象,如下面中的Magic
def get_name(self):
return self.name
Magic = Person("Magic")
print Magic.name

Ein Javascript-Beispiel:

window.name = "Magic from window"
var get_name = function(){
    // this的具体指向只能在运行时才能确定,也就是确定运行时调用其的对象
    return this.name;   
};
// 输出Magic from window, get_name调用的对象为window
alert(get_name());  
var obj = {}
obj.name = "Magic from obj";
// 输出Magic from obj, 我们强制地使用了 apply来更改调用的对象,使其指向obj
alert(get_name.apply(obj)); 
var innerobj = {
    "name" : "Magic from innerobj"
};
innerobj.get_name = get_name;   // 使得innerobj的get_name方法指向了global scope的get_name函数
alert(innerobj.get_name()); // 输出Magic from innerobj, 此时this指向的是innerobj

Aus dem obigen einfachen Beispiel kann dies also immer zur Laufzeit ausgeführt werden, Nur indem es bestimmt wird In einer bestimmten Richtung können wir das aufrufende Objekt kennen. Und das ist auch ein wichtiges Merkmal dynamischer Sprachen.

Wie kann man also das Referenzobjekt bestimmen, auf das dies aktuell zeigt? Dies kann normalerweise wie folgt beurteilt werden:

Wenn es im globalen Bereich aufgerufen wird (siehe Beschreibung unten, um zu klären, was der globale Bereich ist), zeigt es beispielsweise auf das Objektfenster der obersten Ebene von Bowser : get_name()

Wenn es eine Referenz wie diese gibt, innerobj. get_name(), es ist offensichtlich, dass dies auf innerobj

zeigt. Wenn wir apply oder call verwenden, um auf das erzwungene Referenzobjekt zu zeigen, zeigt es offensichtlich auch auf das erzwungene Objekt, z. B. get_name. anwenden(obj).

Über Apply und Call

Diese beiden Schlüsselwörter können leicht als Zwang dieses Referenzobjekts (Laufbereich) verstanden werden. Die Syntax der beiden ist wie folgt:

Spaß .call(object, arg1, arg2, ...)

fun.apply(object, [arg1, arg2, ...])

Der Zweck beider ist der gleiche (dynamisch). Wenn Sie den Laufbereich der Funktion ändern oder das Objekt ändern, auf das dadurch verwiesen wird, unterscheidet sich nur die Aufrufmethode der für die Funktion bereitgestellten Parameter

Der Beispielcode lautet wie folgt:

var test_call_apply = function(name, gender, school){
alert(this.age + name + gender + school);
};
test_call_apply.call({age:24}, "Magic", "male", "ISCAS");
test_call_apply.apply({age:24}, ["Magic", "male", "ISCAS"]);

Bereichsdetails

var global_scope = "I'm global";
var fun = function(){
var fun_scope = "I'm in fun scope";
return innerfun(){
var inner_func_scope = "I'm in the inner fun scope";
return global_scope + fun_scope + inner_func_scope; //此处的引用是重要的,请特别注意
};
};
alert(fun()());

Bitte beachten Sie den obigen Code, wobei:

global_scope der globale Bereich ist

fun_scope, der der Bereich einer Funktion ist

inner_func_scope Es ist der Umfang einer Funktion, der sich innerhalb einer Funktion befindet

Sie können auch weiterhin Funktionen einbetten, dann werden mehrere Bereiche generiert.

Es stellt sich also die Frage, warum die Innerfun-Methode auf Variablen verweisen kann, die nicht in ihrem eigenen Bereich liegen?

Bevor wir diese Frage beantworten, müssen wir das Konzept der Scope-Kette vorstellen. Die sogenannte Bereichskette bezieht sich auf eine Kette von Prioritäts- und zugehörigen Bereichen, die im JavaScript-Code gebildet werden.

Nehmen Sie den obigen Code als Beispiel:

Für den globalen Bereich wird eine globale Bereichskette für sich selbst erstellt (zu diesem Zeitpunkt hat diese Kette natürlich nur einen Bereich).

Für den Umfang der Spaßfunktion wird zunächst eine Bereichskette erstellt, die mit global identisch ist, und dann ein eigener Bereich hinzugefügt (zu diesem Zeitpunkt verfügt diese Kette über zwei Bereiche), ähnlich dieser Struktur: global ==>fun

Für innerfun wird zusätzlich zu der Kette, die der Fun-Funktion gehört, auch ein eigener Bereich hinzugefügt (diese Kette hat derzeit natürlich 3 Bereiche), ähnlich wie hier Struktur: global==>fun==>innerfun

Die Bereichskette hat die folgenden Eigenschaften:

Geordnet

Immer wenn eine Funktion erstellt wird, wird ein Bereich hinzugefügt es zu Ihrer eigenen Bereichskette

Diese Kette ähnelt einem Stapel. Beginnen Sie bei der Suche nach Variablen immer zuerst von oben


Tatsächlich Es ist leicht zu verstehen, dass bei der Berechnung eines Ausdrucks seine eigene Bereichskette von oben nach unten durchsucht wird. Wenn er ihn findet, wird dieser Wert sofort zurückgegeben. Wenn die gesamte Kette nach der Suche nicht gefunden wird, wird er undefiniert zurückgegeben.

Dieser Suchmechanismus bestimmt auch, dass der Bereich, der sich normalerweise am vorderen Ende der Kette befindet, eine höhere Priorität hat.

Wenn Javascript beispielsweise den Ausdruck global_scope + fun_scope + inner_func_scope berechnet, sucht es nach der Bereichskette im obigen Bild, um das Endergebnis zu ermitteln.

一些说明

如果你弄清楚了上面的论述,应该说你对this关键字和scope已经具有完全的知识基础了,但是我们需要在实际中更好地使用和理解这些概念,这样才能把能力上升到别一个层次,这也即所谓的理论与实践的关系。

请看下面这个例子:

var change_color = function(){
this.style.color = "red";
};
window.onload = function(){
var text = document.getElementById("text");
text.onclick = change_color;    //此时this指向的是text这个对象(dom对象)
};
// 下面这行代码是在body中
//这点需要特别注意, inline script指向的是window,此处会无定义  
<span id="another" onclick="change_color()">My color will be changed2.</span>

需要特别注意的是:

inline event registration中的this并非指向的是自己的dom节点,而是global scope的window,这点可以从上面的例子中得到证明

这种inline event registration是不可取的,推荐的是 Unobtrusive JavaScript (处理逻辑和页面结构相分离)

javascript 是一种非常强大的动态语言,它是披着C语言外衣的函数式语言,如果你只当作它是一种类C的命令式语言,那么你的知识层次还过于低,而倘若你能够理解到javascript 的函数式语言本质,你在运用 javascript,理解 jQuery 及其它的库,甚至自己写一些 javascript 都会游刃有余的。


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn