2009-04-02 9 views
25

Das Verhalten von "dies", wenn Funktion bar heißt, ist verwirrend mich. Siehe den folgenden Code. Gibt es eine Möglichkeit zu arrangieren, dass "dies" eine einfache alte js-Objektinstanz ist, wenn der Balken von einem Klick-Handler aufgerufen wird, anstatt das html-Element zu sein?jQuery/JavaScript "dieses" Zeiger Verwirrung

// a class with a method 

function foo() { 

    this.bar(); // when called here, "this" is the foo instance 

    var barf = this.bar; 
    barf(); // when called here, "this" is the global object 

    // when called from a click, "this" is the html element 
    $("#thing").after($("<div>click me</div>").click(barf)); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
+0

Bitte erklären Sie die "Dies ist die foo-Instanz". Die folgende jsfiddle (http://jsfiddle.net/yY6fp/1/) zeigt, dass 'this' in' this.bar() 'zum' window' (globalen) Objekt ausgewertet wird. –

Antwort

33

Willkommen in der Welt von Javascript! : D

Sie sind in den Bereich von Javascript Scope und Schließung gewandert.

Für die kurze Antwort:

this.bar() 

unter den Anwendungsbereich von foo, ausgeführt (als diese-foo bezieht sich)

var barf = this.bar; 
barf(); 

unter der ausgeführt globaler Geltungsbereich.

this.bar im Grunde bedeutet:

die Funktion durch this.bar, die in den Anwendungsbereich dieser (foo) spitz ausgeführt werden. Wenn Sie this.bar in barf kopieren und barf ausführen. Javascript verstanden als, führen Sie die Funktion von Barf, und da es keine dieser, läuft es nur im globalen Bereich.

Um dies zu korrigieren, Sie

barf(); 

zu so etwas wie dies ändern:

barf.apply(this); 

Dies teilt Javascript es vor der Ausführung des Umfangs von diese barf zu binden.

Für jquery-Ereignisse müssen Sie eine anonyme Funktion verwenden oder die Bind-Funktion im Prototyp erweitern, um das Scoping zu unterstützen.

Für weitere Informationen:

+2

Ich bin nicht 100% sicher auf die Terminologie selbst, aber ich denke, diese Antwort (und die damit verknüpften Ressourcen) sind 'Scope' mit 'Ausführungskontext' verwirrend. Das Objekt, auf das "this" zeigt, ist der * Ausführungskontext * und ist völlig unabhängig von * scope * (mit dem Closures zu tun haben). Der Gültigkeitsbereich wird zum Zeitpunkt der Erstellung einer Funktion festgelegt und bestimmt, welche Variablen die Funktion sehen kann. Der Ausführungskontext wird immer dann bestimmt, wenn die Funktion aufgerufen wird, und bestimmt, worauf sich 'this' bezieht. Ersetzen Sie "scope" durch "execution context" hier und nur dann wird es korrekt sein - ich denke! –

1

Dies liegt daran, diese ist immer der Fall, dass die Funktion gebunden ist. Im Fall eines EventHandlers hat die Klasse das Ereignis ausgelöst.

Sie können Sie sich selbst mit einer anonymen Funktion wie diese helfen:

function foo() { 
    var obj = this; 
    $("#thing").after($("<div>click me</div>").click(function(){obj.bar();})); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
2

Sie Function.apply auf die Funktion verwenden können, um festzulegen, was this beziehen soll:

$("#thing").after($("<div>click me</div>").click(function() { 
    barf.apply(document); // now this refers to the document 
}); 
+1

Neben der Tatsache, dass in Ihrem Code eine geschlossene Klammer fehlt - die Funktion * apply * führt sofort die Funktion * barf * aus, anstatt einen Funktionszeiger zurückzugeben. – Martin

+0

Danke, ich habe jetzt den Post korrigiert :) – moff

5

Es gibt eine gute Erklärung auf this Schlüsselwort in JavaScript in QuirksMode verfügbar.

0
this.bar(); // when called here, "this" is the foo instance 

dieser Kommentar ist falsch, wenn foo als eine normale Funktion verwendet wird, nicht als Konstrukteur. hier:

foo();//this stands for window