2017-10-02 1 views
1

Ich habe Zweifel mit Javascript 'this'. Ich verstehe, dass "dies" sich auf das Objekt der aufrufenden Funktion bezieht. In Beispiel 1, wenn wir fordern obj.bar(), warum this.x = 4Verwechslungen mit 'diesem' Schlüsselwort in verschachtelten Funktionen in Javascript

var x = 4, 
obj = { 
    x: 3, 
    bar: function() { 
     var x = 2; 
     setTimeout(function() { 
      var x = 1; 
      alert(this.x); 
     }, 1000); 
    } 
}; 
obj.bar(); 

Ausgang: 4

Und im folgenden Code, warum this.x = 3 und 1 später:

var x = 3; 
var foo = { 
    x: 2, 
    baz: { 
     x: 1, 
     bar: function() { 
      return this.x; 
     } 
    } 
} 
var go = foo.baz.bar; 
alert(go()); 
alert(foo.baz.bar()); 

Output: 3,1

+0

Es ist, weil Sie es in einer anderen Funktion aufrufen (die an 'setTimeout' übergeben wird). –

Antwort

3

gleich Wenn Sie eine Variable auf der obersten Ebene zu erklären, führen Sie eine globale Variable im window Objekt zu erzeugen. Das Schlüsselwort this auf der obersten Ebene bezieht sich auf window.

var x = 4; // same as `window.x = 4`; 
console.log(x); // same as `console.log(this.x)`; 

Wenn Sie obj.bar() nennen, bezieht sich der this Schlüsselwort obj innerhalb von bar. Aber innerhalb setTimeout haben Sie eine andere this, die, die auf den Anrufer des Rückrufs bezieht, die Sie an setTimeout übergeben. Dieser Aufrufer gibt keinen Wert für this an, sondern wird stattdessen zum Objekt window. Daher wird in diesem Code:

setTimeout(function() { 
    var x = 1; 
    alert(this.x); 
}, 1000); 

this.x ist die gleiche wie window.x, die 4 ist, wie Sie es oben im globalen Bereich definiert.

Adressierung Ihr zweites Beispiel, wenn Sie eine Funktion einer Variablen zuweisen verlieren Sie den Kontext, wo diese Funktion kam aus:

var go = foo.baz.bar; 

Wenn Sie jetzt go() Mitteilung nennen es gibt keinen Punkt in diesem Anruf, die bedeutet, dass es keinen expliziten Objektzugriff gibt, dh es gibt keine implizite this.In diesem Fall können Sie noch this vorbei call mit:

// outputs `3` because `this` is `window`, and `window.x` is `3` 
// as declared in the global scope 
alert(go()); 

// Will output `2` because `this` is `foo` 
alert(go.call(foo)); 

// Will output `1` because `this` is `foo.baz` 
alert(go.call(foo.baz)); 

// Will output `1` because the implicit value of `this` is `foo.baz` 
// since we have an explicit object access in this function call 
alert(foo.baz.bar()); 

Sie viele dieser Probleme mit use strict vermeiden können. Im strikten Modus ist this undefiniert, wenn nicht explizit oder implizit definiert, anstatt standardmäßig das Objekt window.

3

this nicht bestimmt wird, wenn die Funktion zu schaffen. Es wird bestimmt, wenn die Funktion aufruft.

Im Falle von setTimeout wird die Funktion gerade ausgeführt, sobald eine bestimmte Zeit verstrichen ist. Es gibt keinen Kontext, daher ruft der Browser die Funktion im globalen Kontext auf. Sie haben eine globale Variable von x=4 deklariert, also ist das was.x entspricht. Wenn Sie den strikten Modus verwenden (indem Sie am Anfang des Skripts "use strict"; hinzufügen), wäre this für den Fall setTimeout nicht definiert und Sie erhalten einen Fehler.

Wenn Sie go() aufrufen, haben Sie eine eigenständige Funktion ohne Kontext, so dass sie im globalen Kontext erneut aufgerufen wird. Dies führt dazu, dass Sie Ihr globales x = 3 verwenden.

Wenn Sie foo.baz.bar() aufrufen, haben Sie endlich einen Kontext. Der Kontext ist foo.baz, so dass das, was this bezieht sich auf, so dass this.x die equivilent von foo.baz.x, die 1.

Verwandte Themen