EMZETT.
Login

Kurz: Mit Klassen (ES2015) beschreibst du Bauanleitungen für Objekte. Unter der Haube nutzt JavaScript weiterhin Prototypen, aber die Klassensyntax ist deutlich lesbarer.

Teil des Kurses JavaScript

Kapitel 21 von 40 im Kurs JavaScript (Abschnitt „Objektorientierung“). Mit Fortschritt, Quiz und Zertifikat auf der Lernseite.

Mit Klassen (ES2015) beschreibst du Bauanleitungen für Objekte. Unter der Haube nutzt JavaScript weiterhin Prototypen, aber die Klassensyntax ist deutlich lesbarer.

Klasse definieren

class Hund {
  constructor(name, alter) {
    this.name = name;
    this.alter = alter;
  }
  bellen() {
    return `${this.name} sagt: Wuff!`;
  }
  get menschenJahre() {
    return this.alter * 7;
  }
}
const rex = new Hund("Rex", 3);
console.log(rex.bellen(), rex.menschenJahre);
console.log(rex instanceof Hund, typeof Hund);

Ausgabe:

Rex sagt: Wuff! 21
true function
  • constructor läuft bei new Hund(...) und setzt die Anfangswerte
  • this ist das neue Objekt
  • Methoden stehen direkt in der Klasse, ohne function
  • get macht aus einer Methode eine berechnete Eigenschaft

Statische Member und private Felder

class Konto {
  #stand = 0;                       // privates Feld (nur in der Klasse sichtbar)
  static anzahl = 0;                // gehört zur Klasse, nicht zum Objekt
 
  constructor(inhaber) {
    this.inhaber = inhaber;
    Konto.anzahl++;
  }
  einzahlen(betrag) {
    if (betrag <= 0) throw new RangeError("Betrag muss positiv sein");
    this.#stand += betrag;
    return this;
  }
  get stand() { return this.#stand; }
  static vergleiche(a, b) { return a.#stand - b.#stand; }
}
const k = new Konto("Mia").einzahlen(100).einzahlen(50);
console.log(k.stand, Konto.anzahl);
console.log(Konto.vergleiche(k, new Konto("Tom")));

Ausgabe:

150 1
150

Der Zugriff k.#stand von außen ist sogar ein Syntaxfehler, schon beim Laden des Programms:

Fehlermeldung:

SyntaxError: Private field '#stand' must be declared in an enclosing class

Echte Privatheit gibt es also mit #. Ein vorangestellter Unterstrich (_stand) ist nur eine Konvention.

Vererbung

class Tier {
  constructor(name) { this.name = name; }
  laut() { return "..."; }
  vorstellen() { return `${this.name} macht ${this.laut()}`; }
}
class Katze extends Tier {
  laut() { return "Miau"; }
}
class Hund extends Tier {
  constructor(name, rasse) {
    super(name);                    // Konstruktor der Oberklasse
    this.rasse = rasse;
  }
  laut() { return "Wuff"; }
  vorstellen() { return super.vorstellen() + ` (${this.rasse})`; }
}
for (const t of [new Katze("Mimi"), new Hund("Rex", "Schäfer"), new Tier("?")]) {
  console.log(t.vorstellen());
}
console.log(new Hund("a", "b") instanceof Tier);

Ausgabe:

Mimi macht Miau
Rex macht Wuff (Schäfer)
? macht ...
true

In einer Unterklasse muss super() aufgerufen werden, bevor du this benutzt.

Prototypen unter der Haube

Jedes Objekt hat einen Verweis auf einen Prototyp, in dem JavaScript nach nicht gefundenen Eigenschaften weitersucht (Prototypenkette):

class A { hallo() { return "A"; } }
class B extends A {}
const b = new B();
console.log(Object.getPrototypeOf(b) === B.prototype);
console.log(Object.getPrototypeOf(B.prototype) === A.prototype);
console.log(b.hallo === A.prototype.hallo, b.hasOwnProperty("hallo"));

Ausgabe:

true
true
true false

Mixins und Komposition

JavaScript erlaubt nur eine Oberklasse. Zusätzliche Fähigkeiten fügst du als Funktion hinzu:

const KannSchwimmen = Basis => class extends Basis {
  schwimmen() { return `${this.name} schwimmt`; }
};
class Tier { constructor(n) { this.name = n; } }
class Ente extends KannSchwimmen(Tier) {}
console.log(new Ente("Donald").schwimmen());

Ausgabe:

Donald schwimmt

this und Methoden als Callback

class Zaehler {
  stand = 0;
  erhoehen = () => { this.stand++; };       // Arrow-Feld: this bleibt gebunden
  falsch() { this.stand++; }
}
const z = new Zaehler();
const f = z.erhoehen, g = z.falsch;
f(); f();
try { g(); } catch (e) { console.log("falsch:", e.name); }
console.log(z.stand);

Ausgabe:

falsch: TypeError
2

Merke

  • class mit constructor, Methoden, get/set und static
  • Private Felder mit #name
  • extends und super für Vererbung
  • Hinter den Klassen steckt die Prototypenkette
  • Methoden als Callback verlieren this: mit Arrow-Feld oder bind lösen

Übungsaufgabe

Baue eine Klasse Rechteck mit breite und hoehe, einer Methode flaeche() und einer Unterklasse Quadrat.

Quiz zur Selbstkontrolle

Weiter im Kurs

Zurück: Reguläre Ausdrücke

Weiter: Fehlerbehandlung

Alle Kapitel: JavaScript im Überblick