Start · Sprachen · JavaScript · Referenz · get

get

Keyword

Die <code>get</code>-Syntax bindet eine Objekteigenschaft an eine Funktion, die bei jedem Lesezugriff auf diese Eigenschaft aufgerufen wird.

seit JavaScript ES5 (berechnete Namen und Klassen-Getter: ES2015) Kategorie: syntax

Signatur

{ get prop() { … } } / { get [expression]() { … } }

Beschreibung

Mit get definierst du eine Accessor-Eigenschaft: Von außen sieht sie aus wie eine normale Eigenschaft (obj.prop), beim Lesen wird aber eine Funktion ausgeführt. Ihr Rückgabewert ist der gelesene Wert. So kannst du Werte bei Bedarf berechnen, abgeleitete Daten liefern (z. B. fullName aus Vor- und Nachname) oder interne Zustände nur lesbar nach außen geben.

Getter gibt es in Objektliteralen, in Klassen (als Instanz-Getter auf dem Prototyp oder als static get) und mit berechneten Namen (get [key]()). Die Getter-Funktion nimmt keine Parameter an. Innerhalb des Getters zeigt this auf das Objekt, über das zugegriffen wurde.

Häufig kombiniert man get mit einem passenden set für dieselbe Eigenschaft. Ohne Setter ist die Eigenschaft praktisch schreibgeschützt: Zuweisungen werden im Sloppy Mode stillschweigend ignoriert und werfen im Strict Mode (und damit in Klassen und Modulen) einen TypeError.

Auf bestehenden Objekten legst du Getter nachträglich mit Object.defineProperty() an. Auslesen lässt sich die Getter-Funktion über Object.getOwnPropertyDescriptor(obj, 'prop').get.

Parameter

Name Typ Default Beschreibung
$prop Pflicht string | Bezeichner Name der Eigenschaft, die an die Getter-Funktion gebunden wird.
$expression any (wird zu string | symbol umgewandelt) Seit ES2015: ein berechneter Eigenschaftsname in eckigen Klammern, z. B. get [Symbol.toStringTag]().

Rückgabewert

Typ
any
Beschreibung
Der Wert, den die Getter-Funktion zurückgibt, ist der Wert beim Lesen der Eigenschaft. Ohne return ergibt sich undefined.

Beispiele

Berechnete Eigenschaft im Objektliteral

const user = {
  firstName: 'Anna',
  lastName: 'Schmidt',
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }
};

console.log(user.fullName);
user.lastName = 'Meier';
console.log(user.fullName); // wird bei jedem Zugriff neu berechnet
Anna Schmidt Anna Meier

Nur-lesbarer Zustand in einer Klasse mit privatem Feld

class Warenkorb {
  #artikel = [];

  add(name, preis) {
    this.#artikel.push({ name, preis });
  }

  get summe() {
    return this.#artikel.reduce((s, a) => s + a.preis, 0);
  }

  get anzahl() {
    return this.#artikel.length;
  }
}

const korb = new Warenkorb();
korb.add('Buch', 19.9);
korb.add('Stift', 2.5);
console.log(korb.anzahl, korb.summe.toFixed(2));

try {
  korb.summe = 0; // Klassen laufen im Strict Mode
} catch (e) {
  console.log(e.constructor.name);
}
2 '22.40' TypeError

Lazy Getter mit Caching und berechnetem Namen

const key = 'config';

const app = {
  get [key]() {
    console.log('Lade Konfiguration …');
    const value = { theme: 'dark', lang: 'de' };
    // Getter durch Dateneigenschaft ersetzen -> nur einmal berechnen
    Object.defineProperty(this, key, { value, writable: false });
    return value;
  }
};

console.log(app.config.theme);
console.log(app.config.lang); // kein erneutes Laden
Lade Konfiguration … dark de

Getter nachträglich mit Object.defineProperty

const temp = { celsius: 21 };

Object.defineProperty(temp, 'fahrenheit', {
  get() {
    return this.celsius * 9 / 5 + 32;
  },
  enumerable: true,
  configurable: true
});

console.log(temp.fahrenheit);
console.log(typeof Object.getOwnPropertyDescriptor(temp, 'fahrenheit').get);
69.8 function

// Wichtig · Fallstricke

  • Keine Parameter: Ein Getter mit Parametern ist ein SyntaxError.
  • Endlosrekursion: Liest der Getter seine eigene Eigenschaft (get name() { return this.name; }), entsteht ein RangeError: Maximum call stack size exceeded. Speichere den Wert in einer anderen Eigenschaft, z. B. einem privaten Feld #name.
  • Ohne Setter schreibgeschützt: Zuweisungen werden im Sloppy Mode ignoriert und werfen im Strict Mode einen TypeError.
  • Performance: Der Getter läuft bei jedem Zugriff. Aufwendige Berechnungen solltest du zwischenspeichern (siehe Lazy-Getter-Beispiel) oder als Methode anbieten, damit Aufrufer die Kosten erkennen.
  • Klassen-Getter liegen auf dem Prototyp und sind nicht aufzählbar. Deshalb tauchen sie nicht in Object.keys(), JSON.stringify() oder beim Spread {...obj} auf. Getter in Objektliteralen sind dagegen aufzählbar, und beim Spread oder bei Object.assign() wird nur ihr aktueller Wert kopiert, nicht der Getter selbst.
  • Im selben Objektliteral kann ein Name nicht gleichzeitig Getter und Dateneigenschaft sein. Die spätere Definition überschreibt die frühere.
  • Kompatibilität: In allen modernen Browsern und in Node.js unterstützt. Das veraltete __defineGetter__() solltest du nicht mehr verwenden.

Siehe auch