this
in Klassen: Struktur, Klarheit – und doch dynamisch
Mit der Einführung von Klassen in ES6 (ECMAScript 2015) hat JavaScript eine vertrautere Syntax für objektorientierte Programmierung erhalten. Viele Entwickler:innen hofften auf eine Vereinfachung der Arbeit mit this
. Tatsächlich bringt die Klassen-Syntax mehr Struktur und Lesbarkeit. Doch unter der Haube bleibt JavaScript dynamisch. Auch in Klassen bleibt this
kontextabhängig und kann verloren gehen, wenn man es falsch verwendet.
In diesem Artikel zeigen wir, wie this
in Klassen wirklich funktioniert, worauf man achten muss, und wie man es effektiv binden kann, sowohl in Konstruktoren als auch mit modernen Features wie Public Class Fields oder Arrow Functions.
this
im Konstruktor: Instanzen korrekt initialisieren
In JavaScript-Klassen referenziert this
innerhalb des Konstruktors immer auf die aktuelle Instanz, die gerade erzeugt wird. Das ist der erwartete und konsistente Teil des Verhaltens.
class User {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hallo, ich bin ${this.name}`);
}
}
const user = new User("Emma");
user.greet(); // "Hallo, ich bin Emma"
Solange man Methoden über das Instanzobjekt (user.greet()
) aufruft, funktioniert this
wie erwartet.
Methoden verlieren this
: Ein Klassiker
Was viele Entwickler:innen überrascht. Auch in Klassen verlieren Methoden ihren Kontext, wenn man sie aus dem Objekt herauslöst, etwa durch Weitergabe an Event-Handler oder als Callback.
const greetFn = user.greet;
greetFn(); // Fehler oder undefined – `this` zeigt nicht mehr auf `user`
Obwohl greet
innerhalb einer Klasse definiert wurde, ist sie dennoch eine ganz normale Funktion. Und wie bei jeder Funktion in JavaScript gilt: Wird sie ohne Objektbezug aufgerufen, ist this
entweder undefined
(im Strict Mode) oder es wirft einen Fehler, da der Bezug zu this nicht mehr besteht (ohne Strict Mode).
Die Lösung: Binden im Konstruktor
Ein bewährtes Muster ist das explizite Binden der Methode an die Instanz innerhalb des Konstruktors. Das funktioniert mit der bind()
-Methode.
class User {
constructor(name) {
this.name = name;
this.greet = this.greet.bind(this);
}
greet() {
console.log(`Hallo, ich bin ${this.name}`);
}
}
const user = new User("Emma");
user.greet(); // "Hallo, ich bin Emma"
const greetFn = user.greet;
greetFn(); // "Hallo, ich bin Emma"
Jetzt zeigt this
immer zuverlässig auf das aktuelle Objekt, auch wenn greet()
außerhalb des Kontexts aufgerufen wird.
Alternativ: Arrow Functions als Klassenmethoden
Seit der Einführung von Public Class Fields kann man Methoden auch als Arrow Functions definieren. Da Arrow Functions kein eigenes this
besitzen, übernehmen sie es vom umgebenden Scope, also von der Instanz.
class User {
constructor(name) {
this.name = name;
}
greet = () => {
console.log(`Hallo, ich bin ${this.name}`);
};
}
const user = new User("Emma");
user.greet(); // "Hallo, ich bin Emma"
const greetFn = user.greet;
greetFn(); // "Hallo, ich bin Emma"
Der Vorteil ist, dass hier kein manuelles Binden nötig ist. Der Nachteil liegt darin, dass diese Methode ist nicht auf dem Prototyp, sondern wird pro Instanz erzeugt sind, was zu höherem Speicherverbrauch führen kann.
this
in Vererbungen und Superklassen
In vererbten Klassen bleibt das this
-Verhalten konsistent. Innerhalb von Unterklassen verweist this
ebenfalls auf die jeweilige Instanz, egal ob sie von der Basisklasse oder der abgeleiteten Klasse stammt.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} macht ein Geräusch`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} bellt`);
}
}
const dog = new Dog("Bello");
dog.speak(); // "Bello bellt"
Auch wenn speak()
in Dog
überschrieben wurde, bleibt this
korrekt auf dog
gesetzt. Das funktioniert selbst dann, wenn innerhalb der Methode super.speak()
aufgerufen wird.
Klassen und Event-Handler: this
richtig weitergeben
Ein häufiger Use-Case ist der Einsatz von Methoden als Event-Handler, etwa im DOM oder in UI-Frameworks. Hier ist besondere Vorsicht geboten, denn Event-Handler verlieren typischerweise ihren Bezug zu this
.
class Button {
constructor(label) {
this.label = label;
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(`Button "${this.label}" wurde geklickt`);
}
}
const b = new Button("Senden");
document.querySelector("button").addEventListener("click", b.handleClick);
Ohne das bind(this)
im Konstruktor wäre this.label
beim Klick undefined
. Alternativ könnte allerdings auch hier eine Arrow Function genutzt werden, um den selben Effekt zu erzielen.
Fazit: Klassen bringen Klarheit – aber this
bleibt dynamisch
JavaScript-Klassen sorgen für strukturierteren Code und helfen dabei, Objektorientierung übersichtlicher umzusetzen. Doch das Verhalten von this
bleibt, wie auch im restlichen JavaScript, dynamisch und abhängig vom Aufrufkontext.
Wer Klassenmethoden außerhalb der Instanz aufruft, muss aktiv dafür sorgen, dass this
korrekt gebunden bleibt, sei es über bind()
, durch Arrow Functions oder moderne Class Fields. Ein klarer, bewusster Umgang mit this
ist auch in Klassen entscheidend für stabilen, wartbaren Code.
Buy me a coffee
Wenn Dir meine Beiträge gefallen und sie Dir bei Deiner Arbeit helfen, würde ich mich über einen “Kaffee” und ein paar nette Worte von Dir freuen.