2016-05-05 13 views
0

Ich versuche, dieses Schlüsselwort in Javascript zu verstehen, ich habe verschiedene Artikel über gelesen, aber es scheint, ich habe noch einige Verwirrung.Bindung an dieses Schlüsselwort in Javascript

Zum Beispiel wollen wir den folgenden Code betrachten:

/* 
* script.js 
*/ 

var data = 'global data'; 

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    } 

}; 


myObj.scope(); // print "object data" 

Also in diesem Fall der Aufrufkontext des Anwendungsbereichs() Funktion ist das Objekt, und diese auf das Objekt selbst gebunden ist.

Lassen Sie uns jetzt einige html hinzufügen ..

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title></title> 
</head> 
<body> 

<input type="button" value="clickme" id="button"> 

<script src="script.js"></script> 

</body> 
</html> 

.. und ein Klick-Ereignis-Listener auf die Schaltfläche den Umfang auslösen() Funktion

document.getElementById("button").addEventListener('click', myObj.scope, false); 

// click on the button => print "undefined" 

Auf dem Click-Ereignis diese verweist zu dem Button-Objekt, das keine Dateneigenschaft hat, so druckt es korrekt undefiniert. Nun möchte ich dieses Problem zur Deklarationszeit mit der Bind-Methode beheben (anstelle von Call oder Apply). So schreibe ich:

/* 
* script.js 
*/ 

var data = 'global data'; 

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    }.bind(this) 

}; 

document.getElementById("button").addEventListener('click', myObj.scope, false); 


myObj.scope(); // print "global data" 

// click on the button => print "global data" 

Es scheint, dass ich an das globale Objekt (Fenster) anstelle von myObj bin. Warum? Was ist der Unterschied zwischen dem dieses Schlüsselwort, das in der Zeile console.log (this.data) im ersten Beispiel verwendet wird und das in der Zeile bind (this) im letzten Beispiel? Sollten sich beide nicht auf das myObj beziehen? Ich bin sicher, ich habe etwas Verwirrung über diesen Punkt, also danke im Voraus für jede Erklärung :)

+0

Sie müssen 'myObj.scope.bind (myObj)' an 'addEventListener' übergeben. Sie können die Funktion nicht innerhalb des Objektliterals binden. – Bergi

+0

Es liegt daran, dass Sie * nur * die Funktion 'myObj.scope' selbst eingegeben haben - denken Sie darüber nach, wie diese Funktion aussieht, wenn Sie sie aus' myObj' herausreißen und als Funktion für sich einfügen; Wie wird es den Umfang wissen, auf den Sie zugreifen möchten? Müssen Ihre Daten so strukturiert sein? Sie sollten stattdessen eine Funktion haben, die einen Parameter mit welchem ​​Gültigkeitsbereich verwendet, um auf –

+0

mögliche Duplikate von [Wie wirkt das "this" -Schlüsselwort in Javascript innerhalb eines Objektliterals?] (Http://stackoverflow.com/q/13441307/1048572) – Bergi

Antwort

0

Why? Which is the difference between the this keyword used in the line console.log(this.data) in the first example and the one used in the line bind(this) in the last example? Should not both refer to the myObj? I am sure I have some confusion about this point, so thanks in advance for any explanation :)

In Ihrem letzten Code-Schnipsel:

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    }bind(this) 

}; 
  1. zunächst einmal, bist du einen Punkt vor bind fehlt, aber ich denke, es Tippfehler nur
  2. bind(this), hier doesn diese‘ t Zeigen Sie auf das Objekt myObj. Dies zeigt auf das globale Objekt. Warum?weil der Kontext, in dem der Code ausgeführt wird, der globale Kontext ist (der Code außerhalb jeder Funktion)
  3. Wenn Sie wirklich den Kontext von myObj.scope an myObj binden möchten, können Sie unten, zur Laufzeit, Sie immer noch nicht tun ‚ll can't read property of undefined Fehler haben:

-

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    }.bind(myObj) 

}; 

Warum? Da das obige Code-Snippet eine JavaScript-Anweisung ist, wurde myObj noch nicht initialisiert, wenn die JavaScript-Engine versucht, die Anweisung zu interpretieren. Es ist während der Initialisierung, also wenn die Funktion bind(myObj), myObj ist undefiniert. Sie müssen es mit 2 Anweisungen tun:

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    } 
}; 
myObj.scope = myObj.scope.bind(myObj) 
+0

Danke! Das ist der Punkt, den ich vermisste. – revy

+0

Nur als eine Randnotiz; Ich möchte Objekte normalerweise mit der Konstruktormethode konstruieren, also mache ich so etwas: function MyObject() { this.scope = this.scope.bind (this); this.data = 'Objektdaten'; } MyObject.prototype.scope = function() { console.log (this.data); }; var myObj = neu MyObject(); Auf diese Weise weiß ich, dass jede konstruierte Instanz diese gebundene Funktion haben wird, ohne sie jedes Mal binden zu müssen, wenn ich ein Objekt konstruiere, indem ich einfach das Schlüsselwort 'new' verwende. –

0

Hier ist die Lösung, müssen Sie den EventHandler an den Kontext, den Sie wollen. Schauen Sie sich das Beispiel unten an klar sein:

var data = 'global data'; 

var myObj = { 
    data: 'object data', 
    scope: function() { 
     console.log(this.data); 
    } 
}; 

document.getElementById("button").addEventListener('click', myObj.scope.bind(myObj), false); 

Wenn Sie mit bind nicht stören wollen, siehe das Beispiel auf ES6 Fat Pfeilen (Sie können es heute nutzen können, lesen Sie einfach über Babeljs). Siehe Beispiel:

var data = 'global data'; 

var myObj = { 
    data: 'object data', 
    scope: function() { 
     console.log(this.data); 
    } 
}; 

document.getElementById("button").addEventListener('click',() => myObj.scope(), false); 

Um mehr zu erfahren, lesen Sie bitte den Artikel (https://john-dugan.com/this-in-javascript/), die diese in 4 einfachen Schritten

+0

beheben kann Um diese Antwort zu erarbeiten: Wenn eine Funktion ohne die Punkt-Syntax aufgerufen wird (so 'Fn()' anstelle von 'object.fn () '), der Geltungsbereich von' this' wird auf 'null' gesetzt, was bedeutet, dass es standardmäßig auf den globalen Gültigkeitsbereich (in einem Browser ist es immer' window') gesetzt wird. Sie können dieses Verhalten außer Kraft setzen, indem Sie die Funktion 'bind()' ausführen, wie in dieser Antwort beschrieben. Unabhängig davon, wie die Funktion aufgerufen wird, bezieht sich "this" auf das, was Sie als erstes Argument in bind() übergeben. –

+0

Danke für die Antwort. Ich werde das als akzeptiert markieren, aber ich verstehe immer noch nicht, warum bind (this) im dritten Beispiel auf das Fensterobjekt und nicht auf myObj verweist. Irgendeine Ahnung? – revy

+0

Yeah @ KlemenSlavič erklärte es sehr gut! revy check the article (Um mehr zu erfahren, lies bitte den Artikel (https://john-dugan.com/this-in-javascript/), der dies in 4 einfachen Schritten erklärt) – punkbit

0

Es erklärt, scheint dies nicht möglich ist, die Funktion auf das Objekt selbst direkt in dem Objekt zu binden , sondern vermehren das Objekt außerhalb der Objektdeklaration zu arbeiten scheint, und Sie haben keine Sorgen zu machen über das Kontext jedes Mal, wenn Sie die Funktion aufrufen möchten, binden:

var myObj = { 
    data: 'object data', 
}; 

myObj.scope = function() { 
    console.log(this.data); 
}.bind(myObj); 

Was denken Sie?

+0

Ja, [das funktioniert] (http://stackoverflow.com/a/10711164/1048572). – Bergi

+0

Danke, genau das, was ich suchte – revy

Verwandte Themen