ProgrammierungFrontend Entwickler

Wie funktioniert der Typisierungsmechanismus von this in Methoden von TypeScript-Klassen bei der Verwendung von normalen und Arrow-Funktionen? Beschreiben Sie die Fallstricke und Best Practices.

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

In TypeScript ist der Typ von this für Methoden innerhalb einer Klasse standardmäßig die aktuelle Instanz der Klasse. Wenn Methoden jedoch als Arrow-Funktionen definiert werden, wird der Kontext von this an den Zeitpunkt der Deklaration gebunden, nicht an den Zeitpunkt des Aufrufs.

Normale Methode:

class Counter { value = 0; increment() { this.value++; } }

Arrow-Funktion:

class Counter { value = 0; increment = () => { this.value++; } }

Finesse:

  • Normale Methoden verlieren den Kontext von this, wenn sie zum Beispiel als Callback übergeben werden (z. B. in Event-Listener).
  • Arrow-Funktionen behalten den Kontext der deklarierten Klasse, sind jedoch im Prototyp nicht sichtbar und werden für jede Instanz neu erstellt.
  • Man kann den Typ von this in der Methodensignatur für zusätzliche Überprüfungen explizit angeben:
class Foo { bar(this: Foo) { // ... } }

Fangfrage.

Was ist der Unterschied zwischen increment() und increment = () => {} in der Klasse? Wie wirkt sich das auf den Kontext von this aus, wenn sie als Callback verwendet werden?

Falsche Antwort:

  • "Es gibt keinen Unterschied zwischen einem Klassenfeld und einer Methode, TypeScript versteht alles von selbst."

Richtige Antwort:

  • Der Kontext von this für eine normale Methode wird zum Zeitpunkt des Aufrufs bestimmt. Wenn man die Methode als Funktion übergibt: setTimeout(counter.increment, 0), wird this zu undefined (im strengen Modus) oder window (im nicht-strengen Modus), während die Arrow-Funktion ihr Umfeld behält:
class Demo { value = 1; inc() { console.log(this.value); } incArrow = () => { console.log(this.value); } } const d = new Demo(); setTimeout(d.inc, 0); // undefined oder Fehler setTimeout(d.incArrow, 0); // 1

Beispiele für reale Fehler aufgrund mangelnden Wissens über die Feinheiten des Themas.


Geschichte

In einem Projekt mit reaktiven Frameworks wurden die Methoden der Klasse direkt als Callbacks ohne explizites Bind übergeben. Infolgedessen wurde this undefined und die Anwendung brach mit einem Fehler beim Zugriff auf this-Eigenschaften zusammen. Das Problem wurde gelöst, indem die Methoden in Arrow-Funktionen umgeschrieben oder explizit gebunden wurden.


Geschichte

Ein Entwickler gab den Typ von this in der Methode explizit an, vergaß jedoch die Typisierung innerhalb der Arrow-Funktion innerhalb dieser Methode. Dies führte dazu, dass this im verschachtelten Callback nicht auf die Instanz der Klasse verwies, sondern auf window. Das Team stieß auf einen Zustandverlust und musste die Ereignisarchitektur überarbeiten.


Geschichte

Eine große UI-Komponente verlangsamte die Anwendung, weil alle Methoden als Arrow-Funktion in der Klasse beschrieben waren (new Counter().increment = ...), was neue Funktionskopien für jede Instanz erzeugte, anstatt eine einzige Definition im Prototyp zu haben, wie es bei einer normalen Methode der Fall wäre. Dadurch erhöhte sich der Speicherverbrauch, und eine Optimierung war nötig.