Ich habe eine Konstruktorfunktion, die einen Ereignishandler registriert:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);
Ich kann jedoch nicht auf die data
Eigenschaft des erstellten Objekts im Rückruf zugreifen . Es sieht so aus, als würde this
es sich nicht auf das erstellte Objekt beziehen, sondern auf ein anderes.
Ich habe auch versucht, eine Objektmethode anstelle einer anonymen Funktion zu verwenden:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
aber es zeigt die gleichen Probleme.
Wie kann ich auf das richtige Objekt zugreifen?
javascript
callback
this
Felix Kling
quelle
quelle
Antworten:
Was Sie wissen sollten
this
this
(auch bekannt als "der Kontext") ist ein spezielles Schlüsselwort in jeder Funktion und sein Wert hängt nur davon ab, wie die Funktion aufgerufen wurde, nicht davon, wie / wann / wo sie definiert wurde. Es wird nicht wie andere Variablen von lexikalischen Bereichen beeinflusst (mit Ausnahme der Pfeilfunktionen, siehe unten). Hier sind einige Beispiele:Weitere
this
Informationen finden Sie in der MDN-Dokumentation .Wie man sich auf das Richtige bezieht
this
Nicht benutzen
this
Sie möchten eigentlich nicht
this
speziell auf das Objekt zugreifen , auf das es sich bezieht . Aus diesem Grund besteht eine einfache Lösung darin, einfach eine neue Variable zu erstellen, die sich auch auf dieses Objekt bezieht. Die Variable kann einen beliebigen Namen haben, aber gebräuchliche sindself
undthat
.Da
self
es sich um eine normale Variable handelt, befolgt sie die Regeln des lexikalischen Bereichs und ist innerhalb des Rückrufs zugänglich. Dies hat auch den Vorteil, dass Sie auf denthis
Wert des Rückrufs selbst zugreifen können .Expliziter Satz
this
des Rückrufs - Teil 1Es könnte so aussehen, als hätten Sie keine Kontrolle über den Wert von,
this
da sein Wert automatisch festgelegt wird, aber das ist tatsächlich nicht der Fall.Jede Funktion hat die Methode
.bind
[docs] , die eine neue Funktion mitthis
an einen Wert gebundenem Wert zurückgibt . Die Funktion hat genau das gleiche Verhalten wie die von Ihnen aufgerufene.bind
, nur dass diesethis
von Ihnen festgelegt wurde. Unabhängig davon, wie oder wann diese Funktion aufgerufen wird,this
wird immer auf den übergebenen Wert verwiesen.In diesem Fall binden wir die Rückrufe
this
an den Wert vonMyConstructor
'sthis
.Hinweis: Verwenden Sie beim Binden des Kontexts für jQuery stattdessen
jQuery.proxy
[docs] . Der Grund dafür ist, dass Sie den Verweis auf die Funktion nicht speichern müssen, wenn Sie einen Ereignisrückruf aufheben. jQuery erledigt das intern.ECMAScript 6: Verwenden Sie Pfeilfunktionen
ECMAScript 6 führt Pfeilfunktionen ein , die als Lambda-Funktionen betrachtet werden können. Sie haben keine eigene
this
Bindung. Stattdessenthis
wird im Gültigkeitsbereich genau wie bei einer normalen Variablen nachgeschlagen. Das heißt, Sie müssen nicht anrufen.bind
. Dies ist nicht das einzige spezielle Verhalten, das sie haben. Weitere Informationen finden Sie in der MDN-Dokumentation.Set
this
des Rückrufs - Teil 2Einige Funktionen / Methoden, die Rückrufe akzeptieren, akzeptieren auch einen Wert, auf den sich die Rückrufe
this
beziehen sollten. Dies ist im Grunde dasselbe wie das Binden selbst, aber die Funktion / Methode erledigt es für Sie.Array#map
[docs] ist eine solche Methode. Seine Unterschrift lautet:Das erste Argument ist der Rückruf und das zweite Argument ist der Wert,
this
auf den Bezug genommen werden soll. Hier ist ein erfundenes Beispiel:Hinweis: Ob Sie einen Wert für übergeben können oder nicht,
this
wird normalerweise in der Dokumentation dieser Funktion / Methode angegeben. Zum Beispiel beschreibt die$.ajax
Methode [docs] von jQuery eine Option namenscontext
:Häufiges Problem: Verwenden von Objektmethoden als Rückruf- / Ereignishandler
Eine weitere häufige Manifestation dieses Problems ist die Verwendung einer Objektmethode als Rückruf- / Ereignishandler. Funktionen sind in JavaScript erstklassige Bürger, und der Begriff "Methode" ist nur ein umgangssprachlicher Begriff für eine Funktion, die ein Wert einer Objekteigenschaft ist. Diese Funktion hat jedoch keinen spezifischen Link zu ihrem "enthaltenden" Objekt.
Betrachten Sie das folgende Beispiel:
Die Funktion
this.method
wird als Klickereignishandler zugewiesen. Wenn Sie jedoch auf klickendocument.body
, wird der Wert protokolliertundefined
, da sich der Wert im Ereignishandlerthis
aufdocument.body
die Instanz von und nicht auf die Instanz von beziehtFoo
.Wie bereits eingangs erwähnt
this
, hängt es davon ab, wie die Funktion aufgerufen wird und nicht davon, wie sie definiert ist .Wenn der Code wie folgt lautet, ist es möglicherweise offensichtlicher, dass die Funktion keinen impliziten Verweis auf das Objekt hat:
Die Lösung ist dieselbe wie oben erwähnt: Wenn verfügbar, verwenden Sie
.bind
diese Option, um explizitthis
an einen bestimmten Wert zu bindenoder rufen Sie die Funktion explizit als "Methode" des Objekts auf, indem Sie eine anonyme Funktion als Rückruf- / Ereignishandler verwenden und das Objekt (
this
) einer anderen Variablen zuweisen :oder verwenden Sie eine Pfeilfunktion:
quelle
self
und sichthat
darauf beziehenthis
. Ich fühle mich so, weilthis
es sich um eine überladene Variable handelt, die in verschiedenen Kontexten verwendet wird. Entsprichtself
normalerweise der lokalen Instanz undthat
bezieht sich normalerweise auf ein anderes Objekt. Ich weiß, dass Sie diese Regel nicht festgelegt haben, da ich sie an einer Reihe anderer Stellen gesehen habe, aber es ist auch der Grund, warum ich angefangen habe, sie zu verwenden_this
, bin mir aber nicht sicher, wie andere sich fühlen, mit Ausnahme der uneinheitlichen Praxis das hat sich ergeben.Function.prototype.call ()
und zu verlassenFunction.prototype.apply ()
. Besonders mitapply ()
habe ich viel Kilometer gesammelt. Ich bin weniger geneigt,bind ()
vielleicht nur aus Gewohnheit zu verwenden, obwohl ich mir bewusst (aber nicht sicher) bin, dass die Verwendung von Bind gegenüber den anderen Optionen geringfügige Overhead-Vorteile haben kann.() => this.clicked()
;)Es gibt verschiedene Möglichkeiten, auf den übergeordneten Kontext im untergeordneten Kontext zuzugreifen:
bind()
Funktion verwenden.1. Verwenden Sie die
bind()
FunktionWenn Sie verwenden
underscore.js
- http://underscorejs.org/#bind2 Speichern Sie den Verweis auf context / this in einer anderen Variablen
3 Pfeilfunktion
quelle
Es ist alles in der "magischen" Syntax des Aufrufs einer Methode:
Wenn Sie die Eigenschaft aus dem Objekt abrufen und auf einmal aufrufen, ist das Objekt der Kontext für die Methode. Wenn Sie dieselbe Methode aufrufen, jedoch in separaten Schritten, ist der Kontext stattdessen der globale Bereich (Fenster):
Wenn Sie die Referenz einer Methode erhalten, ist diese nicht mehr an das Objekt angehängt, sondern nur eine Referenz auf eine einfache Funktion. Das gleiche passiert, wenn Sie die Referenz erhalten, die als Rückruf verwendet werden soll:
Hier würden Sie den Kontext an die Funktion binden:
Wenn Sie jQuery verwenden, sollten Sie
$.proxy
stattdessen die Methode verwenden, da diesbind
nicht in allen Browsern unterstützt wird:quelle
Das Problem mit "Kontext"
Der Begriff „Kontext“ wird manchmal verwendet , um das Objekt durch referenzierte bezieht dies . Seine Verwendung ist ungeeignet , da sie weder semantisch oder technisch mit passt ECMAScript ist dieser .
"Kontext" bezeichnet die Umstände, die etwas umgeben, das Bedeutung hinzufügt, oder einige vorhergehende und folgende Informationen, die zusätzliche Bedeutung verleihen. Der Begriff "Kontext" wird in ECMAScript verwendet, um sich auf den Ausführungskontext zu beziehen , bei dem es sich um alle Parameter, den Bereich und dies innerhalb des Bereichs eines ausgeführten Codes handelt.
Dies wird in Abschnitt 10.4.2 von ECMA-262 gezeigt :
Dies zeigt deutlich, dass dies Teil eines Ausführungskontexts ist.
Ein Ausführungskontext stellt die Umgebungsinformationen bereit, die dem ausgeführten Code Bedeutung verleihen. Es enthält viel mehr Informationen als nur die thisBinding .
Der Wert davon ist also nicht "Kontext", sondern nur ein Teil eines Ausführungskontexts. Es ist im Wesentlichen eine lokale Variable, die durch den Aufruf eines beliebigen Objekts und im strengen Modus auf einen beliebigen Wert gesetzt werden kann.
quelle
this
aber hier wird keiner angeboten, und es ist wohl zu spät, die Tür zum "Kontext" zu schließen.Sie sollten über "dieses" Schlüsselwort Bescheid wissen.
Meiner Ansicht nach können Sie "dies" auf drei Arten implementieren (Selbst- / Pfeilfunktion / Bindungsmethode)
Dieses Schlüsselwort einer Funktion verhält sich in JavaScript etwas anders als in anderen Sprachen.
Es gibt auch einige Unterschiede zwischen dem strengen und dem nicht strengen Modus.
In den meisten Fällen wird der Wert davon bestimmt, wie eine Funktion aufgerufen wird.
Sie kann während der Ausführung nicht durch Zuweisung festgelegt werden und kann bei jedem Aufruf der Funktion unterschiedlich sein.
ES5 führte die bind () -Methode ein, um den Wert einer Funktion festzulegen, unabhängig davon, wie sie aufgerufen wird.
und ES2015 führten Pfeilfunktionen ein, die diese Bindung nicht selbst bereitstellen (sie behält diesen Wert des einschließenden lexikalischen Kontexts bei).
Methode 1: Selbst - Selbst wird verwendet, um einen Verweis auf das Original beizubehalten, selbst wenn sich der Kontext ändert. Diese Technik wird häufig in Event-Handlern verwendet (insbesondere bei Verschlüssen).
Referenz : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
Methode 2 : Pfeilfunktion - Ein Pfeilfunktionsausdruck ist eine syntaktisch kompakte Alternative zu einem regulären Funktionsausdruck.
obwohl ohne eigene Bindungen an this, Argumente, super oder new.target-Schlüsselwörter.
Pfeilfunktionsausdrücke sind als Methoden schlecht geeignet und können nicht als Konstruktoren verwendet werden.
Referenz : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Methode3 : Bind- Die bind () -Methode erstellt eine neue Funktion, die,
Wenn dieses Schlüsselwort aufgerufen wird, wird es auf den angegebenen Wert gesetzt.
mit einer bestimmten Folge von Argumenten vor allen, die beim Aufruf der neuen Funktion angegeben werden.
Referenz: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
quelle
Zunächst müssen Sie ein klares Verständnis
scope
und Verhalten vonthis
Keywords im Kontext von habenscope
.this
&scope
:Kurz gesagt, der globale Bereich bezieht sich auf das Fensterobjekt. Auf in einem globalen Bereich deklarierte Variablen kann von überall aus zugegriffen werden. Andererseits befindet sich der Funktionsbereich innerhalb einer Funktion. Auf die innerhalb einer Funktion deklarierte Variable kann normalerweise nicht von außerhalb der Welt zugegriffen werden.
this
Das Schlüsselwort im globalen Bereich bezieht sich auf das Fensterobjekt.this
Die Funktion inside bezieht sich auch auf das Fensterobjekt. Sothis
wird immer auf das Fenster verwiesen, bis wir eine Möglichkeit findenthis
, einen Kontext unserer Wahl zu manipulieren .Verschiedene Möglichkeiten zur Manipulation von
this
Rückruffunktionen:Hier habe ich eine Konstruktorfunktion namens Person. Es hat eine Eigenschaft namens
name
und vier Verfahren genanntsayNameVersion1
,sayNameVersion2
,sayNameVersion3
,sayNameVersion4
. Alle vier haben eine bestimmte Aufgabe. Akzeptieren Sie einen Rückruf und rufen Sie ihn auf. Der Rückruf hat eine bestimmte Aufgabe, die darin besteht, die Eigenschaft name einer Instanz der Person-Konstruktorfunktion zu protokollieren.Erstellen wir nun eine Instanz aus dem Personenkonstruktor und rufen verschiedene Versionen der
sayNameVersionX
Methode (X bezieht sich auf 1,2,3,4) auf, umniceCallback
zu sehen, auf wie viele Arten wir denthis
internen Rückruf bearbeiten können, um auf dieperson
Instanz zu verweisen .binden :
Mit bind wird eine neue Funktion erstellt, bei der das
this
Schlüsselwort auf den angegebenen Wert gesetzt ist.sayNameVersion1
undsayNameVersion2
verwenden Sie bind, umthis
die Rückruffunktion zu manipulieren .Der erste
this
Rückruf wird mit einem Rückruf innerhalb der Methode selbst gebunden. Der zweite Rückruf wird mit dem daran gebundenen Objekt übergeben.Anruf :
Die
first argument
of-call
Methode wirdthis
innerhalb der Funktion verwendet, mit der aufgerufen wirdcall
angehängten wird.sayNameVersion3
wird verwendetcall
, um das zu manipulierenthis
, um auf das von uns erstellte Personenobjekt anstelle des Fensterobjekts zu verweisen.und es heißt wie folgt:
anwenden :
Ähnlich bezieht sich das
call
erste Argument vonapply
auf das Objekt, das durch angezeigt wirdthis
Schlüsselwort .sayNameVersion4
wirdapply
zum Manipulieren verwendetthis
, um auf ein Personenobjekt zu verweisenund es wird wie folgt aufgerufen. Einfach der Rückruf wird übergeben,
quelle
Wir können dies nicht binden
setTimeout()
, da es immer mit einem globalen Objekt (Fenster) ausgeführt wird. Wenn Siethis
in der Rückruffunktion auf den Kontext zugreifen möchten, können Sie mitbind()
der Rückruffunktion Folgendes erreichen:quelle
Die Frage dreht sich darum, wie sich das
this
Schlüsselwort in Javascript verhält.this
verhält sich anders als unten,this
wird normalerweise durch einen Funktionsausführungskontext bestimmt.this
Bezieht sich im globalen Bereich auf das globale Objekt (daswindow
Objekt).this
sein wirdundefined
als im Strict - Modus bezieht sich global Objektundefined
anstelle derwindow
Objekts.call()
,bind()
undapply()
new
Schlüsselwort (ein Konstruktor) verwendet wird, ist dies an das neu erstellte Objekt gebunden.this
- stattdessen werdenthis
sie lexikalisch gebunden (dh basierend auf dem ursprünglichen Kontext)Wie die meisten Antworten vermuten lassen, können wir die Pfeilfunktion oder die
bind()
Methode oder Self var verwenden. Ich würde einen Punkt über Lambdas (Pfeilfunktion) aus dem Google JavaScript Style Guide zitierenGoogle empfiehlt eindeutig, Lambdas anstelle von bind oder zu verwenden
const self = this
Die beste Lösung wäre also, Lambdas wie folgt zu verwenden:
Verweise:
quelle
this
Dies lag an der Behandlung des Schlüsselworts. Deshalb habe ich meine Antwort in zwei Teile geteilt, einen überthis
und einen über die Verwendung von Funktionen / Methoden als Rückruf. Fühlen Sie sich frei, die Antwort zu bearbeiten.Derzeit ist ein anderer Ansatz möglich, wenn Klassen im Code verwendet werden.
Mit Unterstützung von Klassenfeldern ist es möglich, den nächsten Weg zu gehen:
Sicherlich ist unter der Haube alles alte gute Pfeilfunktion, die den Kontext bindet, aber in dieser Form sieht es viel klarer aus als die explizite Bindung.
Da es sich um einen Vorschlag für Stufe 3 handelt, benötigen Sie Babel und ein entsprechendes Babel-Plugin , um es wie bisher zu verarbeiten (08/2018).
quelle
public methodName = (params) => { body }
innerhalb einer Klasse.Ein anderer Ansatz, der seit DOM2 die Standardmethode zum Binden
this
innerhalb des Ereignis-Listeners ist, mit dem Sie den Listener (unter anderem) immer entfernen können, ist diehandleEvent(evt)
Methode von derEventListener
Schnittstelle:Detaillierte Informationen zur Verwendung
handleEvent
finden Sie hier: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38quelle
this
in JS:Der Wert von
this
in JS wird zu 100% dadurch bestimmt, wie eine Funktion aufgerufen wird und nicht wie sie definiert wird. Wir können den Wert von relativ einfachthis
durch die 'Linke der Punktregel' finden :this
das Objekt links vom Punkt der aufgerufenen Funktionthis
innerhalb einer Funktion häufig das globale Objekt (global
im Knoten,window
im Browser). Ich würde nicht empfehlen, dasthis
Schlüsselwort hier zu verwenden, da es weniger explizit ist als die Verwendung von so etwaswindow
!Function.prototype.bind()
Funktion der Wert von festgelegt werden kannthis
. Dies sind Ausnahmen von der Regel, aber sie sind sehr hilfreich, um den Wert von festzulegenthis
.Beispiel in nodeJS
Ausgabe:
Lassen Sie sich 1: 1 durch die Ausgänge führen (wobei das erste Protokoll ab dem zweiten ignoriert wird):
this
istobj2
wegen der links vom Punkt Regel können wir sehen , wietest1
genannt wirdobj2.test1();
.obj2
ist links vom Punkt und damit derthis
Wert .obj2
links vom Punkt,test2
wirdobj1
über diebind()
Methode gebunden . Also diethis
Wert ist alsoobj1
.obj2
ist links vom Punkt von der Funktion, die aufgerufen wird:obj2.test3()
. Daherobj2
wird der Wert von seinthis
.obj2.test4()
obj2
ist links vom Punkt. Die Pfeilfunktion hat jedoch keine eigenethis
Bindung. Daher wird es an denthis
Wert des äußeren Bereichs gebunden, der der istmodule.exports
Objekt ist, das am Anfang protokolliert wurde.this
von auch mithilfe dercall
Funktion . Hier können wir den gewünschtenthis
Wert als Argument übergeben, wasobj2
in diesem Fall der Fall ist.quelle