JavaScript ist eine Multi-Paradigmen-Sprache, die objektorientierte Programmierung und dynamische Methodenbindung unterstützt - ein leistungsstarkes Konzept, mit dem sich die Struktur von JavaScript-Code während der Programmausführung ändern kann. Dies bietet Entwicklern ernsthafte Möglichkeiten, macht die Sprache flexibel, aber Sie müssen für alles bezahlen. In diesem Fall müssen Sie mit der Klarheit des Codes bezahlen. Ein wesentlicher Beitrag zu diesem Preis leistet das
this
, bei dessen Verhalten viele Dinge gesammelt wurden, die den Programmierer verwirren können.

Dynamische Methodenbindung
Mit der dynamischen Bindung können Sie während der Programmausführung und nicht während der Kompilierung die Methode angeben, die beim Ausführen eines bestimmten Befehls aufgerufen werden muss. In JavaScript wird dieser Mechanismus mithilfe des
this
und der Prototypenkette implementiert. Insbesondere wird der spezifische Wert innerhalb der Methode zur Laufzeit bestimmt, und die Regeln zum Bestimmen dieses Werts variieren in Abhängigkeit davon, wie die Methode deklariert wurde.
Lass uns ein Spiel spielen. Ich nenne es "Was steht darin geschrieben?". Hier ist ihre erste Option - ES6-Modulcode:
const a = { a: 'a' }; const obj = { getThis: () => this, getThis2 () { return this; } }; obj.getThis3 = obj.getThis.bind(obj); obj.getThis4 = obj.getThis2.bind(obj); const answers = [ obj.getThis(), obj.getThis.call(a), obj.getThis2(), obj.getThis2.call(a), obj.getThis3(), obj.getThis3.call(a), obj.getThis4(), obj.getThis4.call(a) ];
Überlegen Sie sich vor dem weiteren Lesen, was in das Antwortarray fällt, und schreiben Sie die Antworten auf. Testen Sie sich anschließend selbst, indem Sie
answers
console.log()
mit
console.log()
. Haben Sie es geschafft, den Wert in jedem Fall korrekt zu "entschlüsseln"?
Wir werden dieses Problem beginnend mit dem ersten Beispiel analysieren. Das Konstrukt
obj.getThis()
gibt
undefined
. Warum? Diese Pfeilfunktion kann nicht gebunden werden. Solche Funktionen verwenden
this
aus ihrem umgebenden lexikalischen Bereich. Die Methode wird im ES6-Modul aufgerufen, in ihrem lexikalischen Bereich ist
this
undefined
. Aus dem gleichen Grund gibt
undefined
einen Aufruf von
obj.getThis.call(a)
. Der Wert für die Arbeit mit
.call()
kann auch mit
.call()
oder
.bind()
nicht neu zugewiesen werden. Dieser Wert entspricht immer dem aus dem lexikalischen Bereich, in dem sich solche Funktionen befinden.
Der Befehl
obj.getThis2()
zeigt, wie Sie damit arbeiten, wenn Sie normale Objektmethoden verwenden. Wenn
this
nicht an eine ähnliche Methode gebunden ist und diese Methode keine Pfeilfunktion ist, dh
this
Bindung unterstützt, wird das Schlüsselwort
this
an das Objekt gebunden, für das die Methode mithilfe der Syntax für den Zugriff auf die Eigenschaften des Objekts aufgerufen wird Punkt oder mit eckigen Klammern.
Das
obj.getThis2.call(a)
ist bereits etwas schwieriger herauszufinden. Mit der
call()
-Methode können Sie eine Funktion mit einem bestimmten Wert aufrufen, der als optionales Argument angegeben wird. Mit anderen Worten, in diesem Fall wird
this
dem Parameter
.call()
entnommen,
.call()
der Aufruf von
obj.getThis2.call(a)
das Objekt
a
zurückgibt.
Verwenden des Befehls
obj.getThis3 = obj.getThis.bind(obj);
Wir versuchen, an
this
Methode zu binden, bei der es sich um eine Pfeilfunktion handelt. Wie wir bereits herausgefunden haben, ist dies nicht möglich. Infolgedessen geben Aufrufe von
obj.getThis3()
und
obj.getThis3.call(a)
undefined
.
Methoden, die gewöhnliche Funktionen sind, können daran angehängt werden, sodass
obj.getThis4()
erwartungsgemäß
obj
. Ein Aufruf von
obj.getThis4.call(a)
gibt
obj
und nicht, wie zu erwarten,
a
. Tatsache ist, dass wir
this
vor dem Aufrufen dieses Befehls bereits mit dem
obj.getThis4 = obj.getThis2.bind(obj);
. Infolgedessen wird bei der Ausführung von
obj.getThis4.call(a)
der Status der Methode berücksichtigt, in der sie sich nach Berücksichtigung der ersten Bindung befand.
Verwenden Sie dies in Klassen
Hier ist die zweite Version unseres Spiels - dieselbe Aufgabe, aber jetzt basierend auf Klassen. Hier verwenden wir die Syntax zum Deklarieren von Feldern für öffentliche Klassen (im Moment befindet sich der
Vorschlag für diese Syntax in der dritten Genehmigungsphase. Er ist standardmäßig in Chrome verfügbar. Sie können ihn mit den
@babel/plugin-proposal-class-properties
)
class Obj { getThis = () => this getThis2 () { return this; } } const obj2 = new Obj(); obj2.getThis3 = obj2.getThis.bind(obj2); obj2.getThis4 = obj2.getThis2.bind(obj2); const answers2 = [ obj2.getThis(), obj2.getThis.call(a), obj2.getThis2(), obj2.getThis2.call(a), obj2.getThis3(), obj2.getThis3.call(a), obj2.getThis4(), obj2.getThis4.call(a) ];
Bevor Sie
answers2
, denken Sie über den Code nach und schreiben Sie Ihre Vision auf, was in das Array
answers2
wird.
Bist du fertig
Hier geben alle Methodenaufrufe mit Ausnahme von
obj2.getThis2.call(a)
einen Verweis auf die Instanz des Objekts zurück. Der gleiche Aufruf gibt das Objekt
a
. Pfeilfunktionen übernehmen
this
immer noch aus dem lexikalischen Bereich. Der Unterschied zwischen diesem und dem vorherigen Beispiel ist der Unterschied im Umfang, aus dem
this
entnommen wird.
Hier arbeiten wir nämlich mit Klasseneigenschaften, die das Verhalten dieses Codes bestimmen.
Tatsache ist, dass während der Vorbereitung des Codes für die Ausführung die Werte wie folgt in die Eigenschaften der Klassen geschrieben werden:
class Obj { constructor() { this.getThis = () => this; } ...
Mit anderen Worten, es stellt sich heraus, dass die Pfeilfunktion im Kontext der Konstruktorfunktion deklariert ist. Da wir mit einer Klasse arbeiten, können Sie sie nur instanziieren, indem Sie das
new
Schlüsselwort verwenden (wenn Sie dieses Schlüsselwort vergessen, wird eine Fehlermeldung angezeigt).
Die wichtigsten Aufgaben, die mit dem
new
Schlüsselwort gelöst werden, bestehen darin, eine neue Instanz des Objekts zu erstellen und
this
an den Konstruktor zu binden. Diese Funktion soll Ihnen helfen, zu verstehen, was gerade passiert, wenn Sie berücksichtigen, worüber wir bereits im vorherigen Abschnitt gesprochen haben.
Zusammenfassung
Haben Sie die in diesem Artikel beschriebenen Aufgaben erledigt? Wenn Sie genau wissen, wie sich
this
Schlüsselwort in JavaScript verhält, sparen Sie beim Debuggen eine Menge Zeit, wenn Sie nach nicht offensichtlichen Gründen für unklare Fehler suchen. Wenn Sie einige der Fragen falsch beantwortet haben, bedeutet dies, dass Sie üben können.
Experimentieren Sie mit dem Beispielcode und versuchen Sie es dann erneut usw., bis Sie alle Fragen richtig beantworten können. Nachdem Sie es selbst herausgefunden haben, finden Sie jemanden, der bereit ist, Ihnen zuzuhören, und erklären Sie ihm, warum die Methoden aus den Aufgaben genau das zurückgeben, was sie zurückgeben.
Wenn Ihnen das alles komplizierter erscheint als erwartet, dann wissen Sie, dass Sie damit nicht allein sind. Ich habe einige Entwickler auf ihr Wissen getestet, und ich denke, dass nur einer von ihnen in all ihren Antworten absolut korrekt war.
Dieses Subsystem der Sprache, das am Anfang wie eine dynamische Suche nach Methoden aussah, die mit
.call()
,
.bind()
oder
.apply()
beeinflusst werden
.call()
,
.bind()
nach dem Auftreten von
.apply()
und -klassen viel komplizierter aus.
Anscheinend wird es nützlich sein, die Hauptmerkmale von Klassen und Pfeilfunktionen zu beachten, um
this
. Denken Sie daran, dass Pfeilfunktionen dies immer aus ihrem lexikalischen Bereich verwenden und das
this
in Klassen tatsächlich an die Konstruktorfunktion der Klasse gebunden ist. Und wenn Sie jemals das Gefühl haben, nicht genau zu wissen, worauf
this
hindeutet, verwenden Sie den Debugger, um Ihre diesbezüglichen Annahmen zu überprüfen.
Denken Sie auch daran, dass Sie in JavaScript viel tun können, ohne
this
in Ihrem Code zu verwenden. Die Erfahrung zeigt, dass fast jeder JS-Code in Form von reinen Funktionen umgeschrieben werden kann, die alle Argumente akzeptieren, mit denen sie arbeiten, und zwar in Form einer explizit angegebenen Liste von Parametern (
this
kann als implizit angegebener Parameter mit einem veränderlichen Status interpretiert werden). Die in reinen Funktionen enthaltene Logik ist deterministisch, was ihre Testbarkeit verbessert. Solche Funktionen haben keine Nebenwirkungen, was bedeutet, dass Sie bei der Arbeit mit ihnen im Gegensatz zur Manipulation wahrscheinlich nichts außerhalb davon „brechen“. Wann immer Sie dies ändern, werden Sie mit einem potenziellen Problem konfrontiert, nämlich dass etwas, das davon abhängt, möglicherweise nicht mehr richtig funktioniert.
Trotz alledem sollte beachtet werden, dass
this
ein nützliches Konzept ist. Beispielsweise kann es angewendet werden, um die gemeinsame Nutzung einer bestimmten Methode durch eine Vielzahl von Objekten zu organisieren. Selbst in der funktionalen Programmierung kann
this
nützlich sein, um andere Methoden von einer Methode eines Objekts aus aufzurufen, sodass Sie basierend auf vorhandenen Konstrukten etwas Neues erstellen können.

