Start · Sprachen · JavaScript · Referenz · set

set

Keyword

Die <code>set</code>-Syntax bindet eine Objekteigenschaft an eine Funktion, die bei jeder Zuweisung an diese Eigenschaft aufgerufen wird.

seit JavaScript ES5 (Objektliterale), ES2015 (Klassen, berechnete Kategorie: syntax

Signatur

{ set prop(val) { /* … */ } }

Beschreibung

Mit set definierst du einen Setter: eine Zugriffseigenschaft, bei der eine Zuweisung wie obj.prop = wert nicht einfach einen Wert speichert, sondern eine Funktion aufruft. Diese bekommt den zugewiesenen Wert als einzigen Parameter. So kannst du Eingaben prüfen, Werte umwandeln, abgeleitete Zustände aktualisieren oder Seiteneffekte auslösen, z. B. eine Neuzeichnung oder ein Änderungs-Event.

Setter kannst du in Objektliteralen, in Klassen (auch als static und mit privaten Namen wie #x) und mit berechneten Eigenschaftsnamen (set [ausdruck](v)) definieren. Meistens hat ein Setter ein passendes get-Gegenstück für dieselbe Eigenschaft. Der eigentliche Wert liegt dann in einem separaten Speicherfeld, am besten in einem privaten Klassenfeld.

Nachträglich an ein bestehendes Objekt hängst du einen Setter mit Object.defineProperty() und einem Deskriptor { set(v) { … } }. Setter in Klassen liegen auf dem Prototyp und sind nicht aufzählbar. Setter in Objektliteralen sind dagegen eigene, aufzählbare Eigenschaften.

Parameter

Name Typ Default Beschreibung
$prop Pflicht string | Symbol | [Ausdruck] Name der Eigenschaft, die an den Setter gebunden wird. Auch berechnete Namen ([ausdruck]) und private Namen (#name) sind möglich.
$val Pflicht any Genau ein Parameter: der Wert, der der Eigenschaft zugewiesen werden soll. Ein Rest-Parameter ist nicht erlaubt. Ein Standardwert (val = 0) ist syntaktisch erlaubt, wird aber praktisch nie genutzt, weil bei einer Zuweisung immer ein Wert übergeben wird.

Rückgabewert

Typ
void
Beschreibung
Den Rückgabewert eines Setters ignoriert JavaScript. Der Zuweisungsausdruck obj.prop = x ergibt immer x, egal was der Setter zurückgibt.

Beispiele

Einfacher Setter im Objektliteral

const sprache = {
  log: [],
  set aktuell(name) {
    this.log.push(name);
  }
};

sprache.aktuell = 'de';
sprache.aktuell = 'en';
console.log(sprache.log);
console.log(sprache.aktuell); // kein Getter vorhanden
['de', 'en'] undefined

Validierung in einer Klasse mit privatem Feld

class Temperatur {
  #celsius = 0;

  get celsius() {
    return this.#celsius;
  }

  set celsius(wert) {
    if (typeof wert !== 'number' || Number.isNaN(wert)) {
      throw new TypeError('Temperatur muss eine Zahl sein');
    }
    if (wert < -273.15) {
      throw new RangeError('Unter dem absoluten Nullpunkt');
    }
    this.#celsius = wert;
  }

  set fahrenheit(f) {
    this.celsius = (f - 32) * 5 / 9; // nutzt den Celsius-Setter
  }
}

const t = new Temperatur();
t.fahrenheit = 212;
console.log(t.celsius);

try {
  t.celsius = -300;
} catch (e) {
  console.log(e.message);
}
100 Unter dem absoluten Nullpunkt

Setter nachträglich mit Object.defineProperty

const einstellungen = { _theme: 'hell' };

Object.defineProperty(einstellungen, 'theme', {
  get() { return this._theme; },
  set(wert) {
    this._theme = wert;
    console.log(`Theme gewechselt: ${wert}`);
  },
  enumerable: true,
  configurable: true
});

einstellungen.theme = 'dunkel';
console.log(einstellungen.theme);
Theme gewechselt: dunkel dunkel

Berechneter Name und Rückgabewert der Zuweisung

const key = 'wert';
const obj = {
  set [key](v) {
    this._v = v * 2;
    return 'ignoriert';
  }
};

const ergebnis = (obj.wert = 5);
console.log(ergebnis, obj._v);
5 10

// Wichtig · Fallstricke

  • Endlosrekursion: Weist du im Setter dieselbe Eigenschaft zu (set name(v) { this.name = v; }), ruft sich der Setter immer wieder selbst auf. Das endet mit RangeError: Maximum call stack size exceeded. Speichere den Wert deshalb in einem anderen Feld, z. B. #name oder _name.
  • Setter ohne Getter: Das Lesen der Eigenschaft liefert undefined. Umgekehrt gilt bei einem Getter ohne Setter: Eine Zuweisung wird im Sloppy-Modus stillschweigend ignoriert und löst im Strict-Modus (also auch in Klassen und Modulen) einen TypeError aus.
  • Ein Setter hat genau einen Parameter. Null oder mehrere Parameter und Rest-Parameter (...args) sind ein SyntaxError.
  • In einem Objektliteral dürfen dieselbe Eigenschaft nicht gleichzeitig ein Setter und ein normaler Datenwert sein. Das spätere Vorkommen überschreibt das frühere.
  • delete obj.prop entfernt den Setter aus Objektliteralen. Setter von Klassen liegen auf dem Prototyp, deshalb bewirkt delete auf der Instanz dort nichts.
  • Kopien per Spread ({...obj}) oder mit Object.assign() rufen Getter auf und kopieren die Werte. Setter werden dabei nicht übernommen. Accessoren kopierst du mit Object.defineProperties(ziel, Object.getOwnPropertyDescriptors(quelle)).
  • Klassenfelder (x = 1;) werden per defineProperty auf der Instanz angelegt. Sie verdecken daher gleichnamige Setter einer Elternklasse, statt sie aufzurufen.
  • Setter sind bequem, verstecken aber Seiteneffekte hinter einer harmlos wirkenden Zuweisung. Halte sie deshalb schnell und vorhersehbar.
  • Kompatibilität: In allen modernen Browsern und in Node.js verfügbar. Private Setter (set #x(v)) gibt es seit ES2022.