Menu

JavaScript Vererbung: extends, super & Overriding

So funktioniert Vererbung in JavaScript-Klassen: extends, super, Methoden überschreiben – und wann Komposition die bessere Wahl ist.

Eine Klasse baut auf einer anderen auf

Mit JavaScript Vererbung lässt du eine Klasse auf dem Bauplan einer anderen aufsetzen und erweiterst sie nach Bedarf. Alle Felder und Methoden der Elternklasse bekommst du geschenkt – und du kannst jederzeit etwas ergänzen oder anpassen:

index.js
Output
Click Run to see the output here.

Dog extends Animal heißt schlicht: "Ein Dog ist ein Animal — nur mit ein bisschen mehr." rex hat selbst keine speak-Methode, aber die Suche läuft die Kette hoch bis zu Animal, wo sie fündig wird. Genau dieses Durchreichen ist der ganze Trick — unter der Haube ist es prototypische Vererbung in JavaScript, nur mit hübscherer Syntax.

super im Konstruktor einer Subklasse

Sobald eine Subklasse einen eigenen Konstruktor hat, gilt eine knallharte Regel: super(...) muss aufgerufen werden, bevor du this anfasst. super ruft den Konstruktor der Elternklasse auf, und der ist es, der das Objekt überhaupt erst anlegt und initialisiert:

index.js
Output
Click Run to see the output here.

Lässt du die Zeile super(name) weg, kassierst du einen ReferenceError, sobald du this liest oder beschreibst. Die Engine weigert sich schlicht, dir ein this auszuhändigen, bevor die Elternklasse ihren Teil erledigt hat.

Deklariert eine Subklasse keinen eigenen Konstruktor, erzeugt JavaScript automatisch einen, der sämtliche Argumente an super durchreicht — du brauchst also nur dann einen eigenen, wenn du zusätzliche Felder setzt oder etwas extra initialisieren willst.

Methoden überschreiben in JavaScript

Eine Subklasse darf jede geerbte Methode neu definieren. Dabei gilt: die nächstgelegene Methode in der Prototypenkette gewinnt:

index.js
Output
Click Run to see the output here.

Hier ist keine Magie im Spiel: Wenn du speak() auf einem Dog aufrufst, sucht die Engine zunächst auf der Instanz selbst nach speak, dann auf Dog.prototype – dort wird sie fündig und hört auf zu suchen. Animal.prototype wird nie erreicht.

Erweitern statt ersetzen: super.method() aufrufen

Manchmal willst du die Methode der Elternklasse gar nicht komplett ersetzen, sondern sie nur ergänzen. Genau dafür gibt es super.method(...) – damit rufst du aus der überschriebenen Methode heraus die Variante der Elternklasse auf:

index.js
Output
Click Run to see the output here.

Genau hier zahlt sich Vererbung aus: die Subklasse nutzt die Logik der Elternklasse weiter, statt sie zu duplizieren. Ändert sich Animal.describe später, übernimmt Dog.describe die Änderung automatisch.

super funktioniert übrigens in jeder Methode – nicht nur im Konstruktor. Es verweist immer auf die Version der Elternklasse von dem, was du gerade aufrufst.

instanceof und die Prototypenkette

Mit instanceof prüfst du, ob die Prototypenkette eines Objekts eine bestimmte Klasse enthält. Jede Instanz einer Subklasse ist gleichzeitig auch eine Instanz ihrer Elternklassen:

index.js
Output
Click Run to see the output here.

Alle vier liefern true. Die Kette läuft Puppy -> Dog -> Animal -> Object, und instanceof hangelt sich da durch. Praktisch für Typprüfungen – in echtem Code brauchst du das allerdings seltener, als man denkt. Meistens ruft man einfach Methoden auf und lässt Polymorphie den Rest erledigen.

Ein etwas größeres Beispiel

Ein typisches Muster: eine Basisklasse mit gemeinsamer Logik und ein paar Subklassen, die sie spezialisieren.

index.js
Output
Click Run to see the output here.

Beachte: describe lebt auf Shape und muss nie neu geschrieben werden – die Methode ruft einfach this.area() auf, und zur Laufzeit landet der Aufruf bei der passenden Subklasse. Genau das ist Polymorphie: dieselbe Aufrufstelle, aber je nach konkretem Objekt ein anderes Verhalten.

Vererbung vs. Komposition in JavaScript

Vererbung wirkt verlockend, weil sie sich produktiv anfühlt – eine Zeile Code, und du bekommst einen Haufen Methoden geschenkt. Sobald die Hierarchien wachsen, altert sie allerdings ziemlich schlecht.

Faustregel: Greif nur dann zu extends, wenn die Beziehung klar ein "X ist ein Y" ist und die Subklasse wirklich den Großteil des Verhaltens der Elternklasse teilt. Willst du hingegen bloß eine oder zwei Hilfsmethoden mitnutzen, ist Komposition die bessere Wahl – dann bekommt die Klasse einfach ein Feld, das das Hilfsobjekt hält:

index.js
Output
Click Run to see the output here.

Tiefe Vererbungshierarchien (Animal -> Mammal -> Dog -> WorkingDog -> PoliceDog) sehen in Diagrammen schick aus, machen im Code aber schnell Ärger — eine kleine Änderung nahe der Wurzel pflanzt sich unberechenbar durch sämtliche Nachfahren fort. Die meisten gesunden Codebasen bleiben ein bis zwei Ebenen flach und setzen für den Rest auf Komposition.

Weiter geht's: Statische Member

Alles in diesem Dokument lebt auf Instanzen — also Methoden, die du über new Thing().something() aufrufst. Manchmal brauchst du aber Methoden oder Daten, die zur Klasse selbst gehören und nicht zu einer einzelnen Instanz. Genau dafür gibt es static, und darum geht's als Nächstes.

Häufig gestellte Fragen

Wie funktioniert Vererbung in JavaScript?

Eine Klasse erbt mit extends von einer anderen. Die Unterklasse übernimmt alle Methoden und Felder der Elternklasse und kann eigene hinzufügen oder vorhandene überschreiben. Intern verknüpft JavaScript den Prototyp der Unterklasse mit dem der Elternklasse – so landen Methodenaufrufe automatisch oben im Prototype Chain, wenn sie unten nicht gefunden werden.

Was macht super in JavaScript?

super(...) ruft den Konstruktor der Elternklasse auf – und zwar zwingend, bevor du in einem Subklassen-Konstruktor auf this zugreifen darfst. Mit super.methode(...) rufst du die Variante der Elternklasse einer Methode auf. Genau so erweiterst du Verhalten, statt es komplett zu ersetzen.

Vererbung oder Komposition – was ist besser in JavaScript?

Vererbung passt, wenn es wirklich eine „ist ein"-Beziehung gibt und die Unterklasse den Großteil des Verhaltens der Elternklasse teilt. Willst du dagegen einfach nur Funktionalität wiederverwenden, greif zu Komposition – also Objekte, die andere Objekte in sich halten. Tiefe Klassenhierarchien altern erfahrungsgemäß schlecht; in realen Codebases bleibt es meistens bei ein, zwei Ebenen.

Lerne mit Coddy zu programmieren

LOS GEHT'S