Vererbung und Prototypen in JavaScript
Vererbung und Prototypen in JavaScript
~15 Min. Lesezeit Zuletzt aktualisiert am 8. August 2026
Wir erweitern unser Kontensystem um einen SPEZIALISIERTEN Kontotyp – ein Sparkonto mit Zinsen – und lernen dabei, was class/extends unter der Haube TATSÄCHLICH tut: JavaScripts Prototyp-System.
extends und super
import { Konto } from './konto.js';
export class Sparkonto extends Konto {
constructor(name, startguthaben, zinssatz) {
super(name, startguthaben); // ruft den Konto-Konstruktor auf - PFLICHT vor 'this'!
this.zinssatz = zinssatz;
}
jahresZinsenGutschreiben() {
const zinsen = this.kontostand * (this.zinssatz / 100);
this.buchen('Jahreszinsen', zinsen, 'Zinsen'); // 'buchen' von Konto GEERBT
return zinsen;
}
formatiereKontostand() {
return `${super.formatiereKontostand()} (${this.zinssatz}% Zinsen)`; // ÜBERSCHREIBEN + Basisverhalten aufrufen
}
}import { Sparkonto } from './sparkonto.js';
const sparkonto = new Sparkonto('Tagesgeld', 5000, 2.5);
sparkonto.jahresZinsenGutschreiben();
console.log(sparkonto.formatiereKontostand()); // 'Tagesgeld: 5125.00 EUR (2.5% Zinsen)'
console.log(sparkonto instanceof Konto); // true - Sparkonto IST-EIN Kontosuper(...) im Konstruktor ruft den Konstruktor der BASISKLASSE auf – verpflichtend, BEVOR this im abgeleiteten Konstruktor verwendet werden darf. super.formatiereKontostand() in einer überschriebenen Methode ruft die ORIGINAL-Implementierung der Basisklasse auf, statt sie komplett zu ersetzen.
Was class WIRKLICH ist: das Prototyp-System
JavaScript hat KEINE klassenbasierte Vererbung im Sinne von Java oder C# – class ist "syntaktischer Zucker" über einem älteren, DYNAMISCHEREN Mechanismus: der Prototypenkette. Jedes Objekt hat eine interne Verbindung zu einem anderen Objekt, seinem "Prototyp" – fehlt eine Eigenschaft auf dem Objekt selbst, sucht JavaScript automatisch entlang dieser Kette weiter:
function KontoAlt(name, kontostand) {
this.name = name;
this.kontostand = kontostand;
}
// Methoden auf dem PROTOTYP definieren, statt bei jeder Instanz neu:
KontoAlt.prototype.formatiereKontostand = function () {
return `${this.name}: ${this.kontostand.toFixed(2)} EUR`;
};
const konto = new KontoAlt('Girokonto', 1500);
console.log(konto.formatiereKontostand()); // 'Girokonto: 1500.00 EUR'
// 'konto' hat KEINE eigene 'formatiereKontostand'-Eigenschaft -
// JavaScript findet sie über die Prototypenkette auf KontoAlt.prototypeDies ist EXAKT dasselbe Muster, das class automatisch für uns erzeugt – Methoden, die in einem class-Körper definiert werden, landen intern auf dem Prototyp der Klasse, nicht auf jeder einzelnen Instanz. Das erklärt auch, warum Methoden SPEICHEREFFIZIENT geteilt werden: Es existiert nur EINE Kopie jeder Methode, egal wie viele Konto-Instanzen erzeugt werden.
Die Prototypenkette bei extends
console.log(Object.getPrototypeOf(sparkonto) === Sparkonto.prototype); // true
console.log(Object.getPrototypeOf(Sparkonto.prototype) === Konto.prototype); // true
console.log(sparkonto instanceof Sparkonto); // true
console.log(sparkonto instanceof Konto); // true - über die Kette gefunden
console.log(sparkonto instanceof Object); // true - JEDES Objekt endet letztlich hierTipp: Für den Alltag reicht es, class/extends/super zu beherrschen – das Prototyp-Wissen aus diesem Abschnitt erklärt aber, WARUM sich JavaScript so verhält, und hilft beim Verständnis von Fehlermeldungen wie "X is not a function" (die Methode existiert weder auf dem Objekt noch irgendwo in seiner Prototypenkette).
Polymorphie: dieselbe Methode, unterschiedliches Verhalten
const konten = [
new Konto('Girokonto', 1500),
new Sparkonto('Tagesgeld', 5000, 2.5),
];
for (const konto of konten) {
// JEDES Konto ruft SEINE EIGENE formatiereKontostand()-Version auf - Polymorphie
console.log(konto.formatiereKontostand());
}
// 'Girokonto: 1500.00 EUR'
// 'Tagesgeld: 5000.00 EUR (2.5% Zinsen)'