Start · Sprachen · JavaScript · Referenz · extends

extends

Keyword

Mit <code>extends</code> legst du eine Klasse als Unterklasse einer anderen Klasse oder Konstruktorfunktion an und erbst deren Methoden und Eigenschaften.

seit JavaScript ES2015 Kategorie: syntax

Signatur

class ChildClass extends ParentClass { /* … */ }

Beschreibung

Das Schlüsselwort extends steht in Klassendeklarationen (class A extends B {}) und Klassenausdrücken (const A = class extends B {}). Es richtet zwei Prototypketten ein: Child.prototype erbt von Parent.prototype (Instanzmethoden), und Child selbst erbt von Parent (statische Methoden und Eigenschaften).

Rechts von extends darf jeder Ausdruck stehen, der einen Konstruktor ergibt: eine Klasse, eine klassische Konstruktorfunktion, ein eingebautes Objekt wie Array, Error oder Map, ein Funktionsaufruf (Mixins) oder null. Dadurch kannst du eigene Fehlertypen, erweiterte Collections oder Custom Elements (extends HTMLElement) bauen.

Hat die Unterklasse einen eigenen constructor, musst du dort super(...) aufrufen, bevor du this verwendest oder den Konstruktor verlässt. Ohne eigenen Konstruktor ergänzt die Engine automatisch constructor(...args) { super(...args); }. Überschriebene Methoden erreichst du über super.methode().

Parameter

Name Typ Default Beschreibung
$ChildClass Bezeichner Name der neuen Unterklasse. Bei Klassenausdrücken optional.
$ParentClass Pflicht Function | null Ausdruck, der einen Konstruktor (mit prototype-Eigenschaft, die ein Objekt oder null ist) oder null ergibt. Er wird einmal ausgewertet, wenn die Klasse definiert wird.

Rückgabewert

Typ
Function
Beschreibung
Bei Klassenausdrücken der neue Klassenkonstruktor. Klassendeklarationen legen eine Bindung im aktuellen Gültigkeitsbereich an.

Beispiele

Einfache Vererbung mit super

class Tier {
  constructor(name) {
    this.name = name;
  }
  sprich() {
    return `${this.name} macht ein Geräusch.`;
  }
}

class Hund extends Tier {
  constructor(name, rasse) {
    super(name); // muss vor this stehen
    this.rasse = rasse;
  }
  sprich() {
    return `${super.sprich()} Wuff! (${this.rasse})`;
  }
}

const bello = new Hund('Bello', 'Dackel');
console.log(bello.sprich());
console.log(bello instanceof Tier);
Bello macht ein Geräusch. Wuff! (Dackel) true

Eigener Fehlertyp auf Basis von Error

class HttpError extends Error {
  constructor(status, message) {
    super(message);
    this.name = 'HttpError';
    this.status = status;
  }
}

const ladeDaten = async (url) => {
  const res = await fetch(url);
  if (!res.ok) throw new HttpError(res.status, `Fehler beim Laden von ${url}`);
  return res.json();
};

try {
  throw new HttpError(404, 'Nicht gefunden');
} catch (err) {
  if (err instanceof HttpError) console.log(err.name, err.status, err.message);
}
HttpError 404 Nicht gefunden

Eingebaute Klassen erweitern und statische Vererbung

class Stapel extends Array {
  get oben() {
    return this[this.length - 1];
  }
  static aus(...werte) {
    return this.of(...werte); // erbt Array.of
  }
}

const s = Stapel.aus(1, 2, 3);
s.push(4);
console.log(s.oben);
console.log(s.map((x) => x * 2) instanceof Stapel);
4 true

Mixin: Ausdruck hinter extends

const Zeitstempel = (Basis) => class extends Basis {
  constructor(...args) {
    super(...args);
    this.erstellt = new Date(0).toISOString();
  }
};

class Benutzer {
  constructor(name) { this.name = name; }
}

class ProtokollierterBenutzer extends Zeitstempel(Benutzer) {}

const u = new ProtokollierterBenutzer('Anna');
console.log(u.name, u.erstellt);
Anna 1970-01-01T00:00:00.000Z

// Wichtig · Fallstricke

  • super vor this: Wird this im Konstruktor einer Unterklasse vor super() angesprochen, gibt es einen ReferenceError. Dasselbe gilt, wenn der Konstruktor endet, ohne super() aufzurufen (außer er gibt explizit ein Objekt zurück).
  • Ungültige Elternklasse: Ergibt der Ausdruck weder einen Konstruktor noch null (z. B. eine Pfeilfunktion oder ein einfaches Objekt), wird ein TypeError geworfen. Auch Pfeilfunktionen kannst du nicht erweitern, weil sie keine Konstruktoren sind.
  • extends null: ist erlaubt, aber heikel: Der automatisch erzeugte Konstruktor ruft super() auf und scheitert. Du brauchst einen eigenen Konstruktor, der ein Objekt zurückgibt (etwa mit Object.create(new.target.prototype)).
  • Einfachvererbung: JavaScript erlaubt nur eine Elternklasse. Für mehrere Verhaltensweisen nimmst du Mixins (siehe Beispiel) oder Komposition.
  • Eingebaute Klassen: Unterklassen von Error, Array oder Map funktionieren nur mit echter ES2015-Klassensyntax richtig. Werden sie zu ES5 transpiliert (ältere Babel-/TypeScript-Ziele), kann instanceof falsch sein. Array-Methoden wie map geben über Symbol.species Instanzen der Unterklasse zurück.
  • Kompatibilität: Wird von allen aktuellen Browsern und von Node.js ab Version 6 unterstützt. Klassenkörper laufen immer im Strict Mode.