W3docs

JavaScript Klassenvererbung

JavaScript Klassenvererbung mit extends und super: Prototypkette, Methoden- und Eigenschaftsüberschreibung, Elterncode aufrufen, Built-ins erweitern und statische Methoden erben.

Einführung in die JavaScript Klassenvererbung

Klassenvererbung ist ein grundlegendes Konzept der objektorientierten Programmierung, das einer Klasse ermöglicht, Eigenschaften und Methoden von einer anderen Klasse zu erben. In JavaScript wird die Klassenvererbung mit dem Schlüsselwort extends implementiert und bietet eine Möglichkeit, eine Klasse als abgeleitete Klasse zu erstellen, die von einer Basisklasse erbt.

Weitere Informationen zur grundlegenden Syntax finden Sie unter JavaScript: Klassen und grundlegende Syntax.

Dieses Kapitel behandelt, wie abgeleitete Klassen erstellt werden, wie Methoden und Eigenschaften überschrieben werden, wie mit super auf die Elternklasse zugegriffen wird, wie Built-in-Klassen wie Array erweitert werden und wie statische Methoden geerbt werden — sowie die Prototypkette, die das alles im Hintergrund ermöglicht.

Wie Vererbung funktioniert: Die Prototypkette

Das Schlüsselwort class ist syntaktischer Zucker über JavaScripts prototypischer Vererbung. Wenn Sie class Circle extends Shape schreiben, stellt die Engine zwei Verbindungen her:

  • Circle.prototype.__proto__ === Shape.prototype — damit Instanzmethoden in der Kette aufgelöst werden.
  • Circle.__proto__ === Shape — damit auch statische Methoden geerbt werden.

Wenn Sie eine Eigenschaft lesen oder eine Methode auf einem object aufrufen, schaut die Engine zuerst beim object selbst nach. Wenn sie dort nicht gefunden wird, geht sie die Prototypkette hinauf — zu Circle.prototype, dann Shape.prototype, dann Object.prototype, dann null — und stoppt beim ersten Treffer. Genau deshalb kann eine Instanz von Circle eine Methode aufrufen, die auf Shape definiert ist.

javascript— editable

Object.getPrototypeOf(obj) gibt das nächste Glied in der Kette zurück (die standardmäßige, bevorzugte Methode zur Inspektion). Der veraltete obj.__proto__-Accessor zeigt auf dasselbe object. Das Verständnis dieser Kette erklärt alles Folgende: Überschreiben funktioniert, weil ein näheres Prototyp einen weiter entfernten überschattet, und super funktioniert, weil es explizit zum Prototyp des übergeordneten Elements springt.

Eine abgeleitete Klasse erstellen

Um eine Klasse zu erstellen, die von einer anderen erbt, verwenden wir das Schlüsselwort extends:

javascript— editable

In diesem Beispiel erweitert Circle die Klasse Shape, was bedeutet, dass es die Eigenschaften und Methoden von Shape erbt und gleichzeitig eigene Methoden bereitstellt. Beachten Sie, dass Circle keinen eigenen Konstruktor definiert. In JavaScript rufen abgeleitete Klassen ohne expliziten Konstruktor automatisch super() mit denselben Argumenten auf, die dem Konstruktor der abgeleiteten Klasse übergeben wurden.

Methoden überschreiben

Abgeleitete Klassen können Methoden ihrer Basisklassen überschreiben, um ein für die Unterklasse spezifisches Verhalten bereitzustellen.

javascript— editable

Hier überschreibt Circle die Methode print, um seinen spezifischen Typ widerzuspiegeln.

Elternmethoden mit super aufrufen

Sie können auch eine Methode der Elternklasse innerhalb der abgeleiteten Klasse mit super.methodName() aufrufen. Dies ist nützlich, wenn Sie das Verhalten der Elternklasse erweitern möchten, anstatt es vollständig zu ersetzen.

javascript— editable

Hier führt super.print() die Logik der Elternklasse aus, bevor die unterklassenspezifische Ausgabe hinzugefügt wird.

Eine realistische Überschreibung: Fläche berechnen

Überschreiben glänzt besonders dann, wenn jede Unterklasse ein wirklich anderes Verhalten benötigt. Hier definiert eine Basis-Shape die gemeinsame Schnittstelle, und jede Unterklasse überschreibt area() mit ihrer eigenen echten Berechnung. Der Aufruf von area() auf einem Circle wird zu Circle.prototype.area aufgelöst, das die Basisversion überschattet.

javascript— editable

Beachten Sie, dass describe() nur auf Shape definiert ist, aber this.area() aufruft und die Unterklassen-Implementierung erhält. Das ist die Prototypkette in Aktion: this bezieht sich immer auf die tatsächliche Instanz, sodass die Methodensuche von Circle oder Rectangle aus beginnt.

Eigenschaften überschreiben und super.prop lesen

super ist nicht auf Methoden beschränkt — Sie können eine Eigenschaft, die auf dem Elternprototyp definiert ist, mit super.prop lesen. Das ist praktisch, wenn eine Unterklasse auf dem Getter des Elternteils aufbauen möchte, anstatt ihn zu ersetzen.

javascript— editable

Auf den Elternkonstruktor zugreifen: Schlüsselwort super

Wenn eine Klasse eine andere Klasse erweitert, muss die Konstruktorfunktion der abgeleiteten Klasse den Konstruktor der Elternklasse mit super() aufrufen, bevor sie this verwenden kann. So wird super in Konstruktoren verwendet, um sicherzustellen, dass die Elternklasse initialisiert wird:

javascript— editable

Warum super() vor this ausgeführt werden muss

In einer abgeleiteten Klasse wird das Instanzobjekt erst erstellt, wenn super() ausgeführt wird — das ist die Aufgabe des Elternkonstruktors. Bis dahin befindet sich this in einem uninitialisierten Zustand, sodass jede Berührung davon (Lesen, Zuweisen oder implizites Zurückgeben des Objekts) einen ReferenceError auslöst. Dies ist eine Sprachregel, keine Stilpräferenz.

javascript— editable

Eine verwandte Regel: Wenn eine abgeleitete Klasse einen Konstruktor definiert, muss sie irgendwo vor dessen Ende super() aufrufen, sonst wird derselbe ReferenceError ausgelöst. (Eine abgeleitete Klasse ohne expliziten Konstruktor ist in Ordnung — JavaScript fügt automatisch constructor(...args) { super(...args); } ein.) Sobald super() zurückkehrt, ist this vollständig initialisiert und einsatzbereit.

Statische Methoden erben

Statische Member gehören zur Klasse selbst, nicht zu Instanzen. Da extends auch Circle.__proto__ mit Shape verknüpft, erben abgeleitete Klassen statische Methoden und können diese direkt aufrufen. Weitere Informationen zur Deklaration finden Sie unter JavaScript Statische Eigenschaften und Methoden.

javascript— editable

Innerhalb einer statischen Methode bezieht sich this auf die Klasse, für die sie aufgerufen wurde, sodass Shape.create, das als Circle.create aufgerufen wird, ein Circle erstellt.

Mehrstufige Vererbung

Ketten können mehr als zwei Ebenen tief sein. Die Methodensuche geht einfach weiter die Prototypkette hinauf, und super bezieht sich immer auf den Prototyp eine Ebene über der Klasse, in der die Methode definiert ist.

javascript— editable

Built-in-Klassen erweitern

Sie können native Klassen wie Array, Error oder Map erweitern, um spezialisierte Versionen zu erstellen, die das gesamte Built-in-Verhalten beibehalten und gleichzeitig eigene Funktionen hinzufügen.

javascript— editable

Der Symbol.species-Fallstrick. Methoden wie map, filter und slice geben eine neue Sammlung zurück. Standardmäßig geben sie eine Instanz Ihrer Unterklasse zurück (MyArray), nicht ein einfaches Array — was in der Regel in Ordnung ist, aber Code überraschen kann, der ein echtes Array erwartet. Sie können zu einfachen arrays zurückkehren, indem Sie den statischen Symbol.species-Getter überschreiben.

javascript— editable

Informationen zum Kombinieren von Verhalten aus mehreren Quellen (JavaScript unterstützt keine Mehrfachvererbung) finden Sie unter JavaScript Mixins.

Zusammenfassung

Wichtige Erkenntnisse:

  • Verwenden Sie extends, um eine Klasse abzuleiten; dabei werden sowohl die Prototypkette (Instanzmethoden) als auch die Klasse selbst (statische Methoden) mit der Elternklasse verknüpft.
  • Die Methoden- und Eigenschaftssuche geht die Prototypkette hinauf und stoppt beim ersten Treffer — deshalb überschreibt eine näher liegende Definition eine weiter entfernte. Untersuchen Sie die Kette mit Object.getPrototypeOf().
  • Rufen Sie in einem abgeleiteten Konstruktor super() vor this auf. Bis super() ausgeführt wird, ist die Instanz uninitialisiert, und jede Verwendung von this löst einen ReferenceError aus.
  • Greifen Sie explizit auf das Verhalten der Elternklasse mit super.method() oder super.prop zu, auch wenn Sie es überschrieben haben.
  • Sie können Built-ins wie Array erweitern — achten Sie jedoch auf das Symbol.species-Verhalten, wenn Methoden neue Sammlungen zurückgeben.

Nächste Schritte:

Übungen

Übung
Welche Aussagen zur JavaScript-Klassenvererbung sind wahr?
Welche Aussagen zur JavaScript-Klassenvererbung sind wahr?
Was this page helpful?