2015-05-27 9 views
7

Ich habe eine einfache JSFiddle here zeigt mein Problem.Verlieren "dieses" Kontext in JavaScript bei der Weitergabe von Mitgliedern

Ich habe diesen JavaScript-Code:

var b = document.getElementById("b"); 

function A() { 
    this.f = "1"; 
} 

A.prototype.t = function() { 
    b.innerHTML = this.f; 
}; 

var a = new A(); 

var l = a.t; 
l(); 

Warum ist this undefiniert, wenn ich versuche a.t zu anrufen? Wie stelle ich diesen Kontext wieder her, ohne allzu ausführlich zu sein oder zu viel zu speichern?

Antwort

12

Warum ist das nicht definiert, wenn ich versuche, a.t aufzurufen?

Da in JavaScript wird this in erster Linie durch gesetzt, wie die Funktion genannt wird, nicht wo es definiert. a.t() setzt this auf a innerhalb des Anrufs, aber l() setzt this entweder auf undefined (im strikten Modus) oder das globale Objekt (im lockeren Modus).

Mehr (auf meinem Blog):

Die einzigen Ausnahmen sind "gebunden" Funktionen (wie bei Function#bind) oder ES6 der "Pfeil" Funktionen (die ihre this aus dem Kontext erhalten, in dem sie definiert sind).

Wie kann ich diesen Kontext wiederherstellen, ohne übermäßig ausführlich zu sein oder zu viel zu speichern?

Function#bind ist in der Regel eine gute Antwort:

var l = a.t.bind(a); 
l(); 

Es gibt eine neue Funktion, die, wenn sie aufgerufen wird, das Original mit this Satz auf das erste Argument nennt man bind gab. (Sie können auch andere Argumente binden.) Es handelt sich um eine ES5-Funktion, aber wenn Sie wirklich alte Browser unterstützen müssen, können Sie sie problemlos auffüllen.


Wenn Sie nur Anruf benötigenl mit einem bestimmten this Wert, und nicht immer haben sie diesen Wert verwenden, wie Robert Rossmann points out können Sie verwenden Function#call oder Function#apply:

l.call(this, 'a', 'b', 'c'); // Calls `l` with `this` set to `a` and args 'a', 'b', and 'c' 
l.apply(this, ['a', 'b', 'c']); // Calls `l` with `this` set to `a` and args 'a', 'b', and 'c' -- note they're specified in an array 
+1

Alternativ kann man ['Funktion.prototype.call'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call), wenn die Funktion nicht weitergegeben werden muss und nur aufgerufen werden muss einmal: 'var l = at; l.call (a); ' –

+0

Wäre der Code des ursprünglichen Askers gültig, wenn' A.t() 'in der ursprünglichen 'A'-Funktion definiert wäre? Auf diese Weise könnte die Funktion auf eine Variable mit privatem Gültigkeitsbereich zugreifen ([wie diese] (http://jsfiddle.net/lun471k/re8vdadt/1/)). –

+0

@RobertRossmann könnten Sie das demonstrieren? – eatonphil

1

JavaScript funktionell ist Bereich,

Um eine Funktion mit dem richtigen Wert für diese auszuführen, müssen Sie es an das richtige Objekt binden. Beispiel:

var l= a.t.bind(a); 
0

Da sich der Kontext ändert, wenn Sie die Funktion einer neuen Variablen zuweisen. Sie könnten immer einfach a.t(); tun.

Verwandte Themen