Signatur
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
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
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);
}
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);
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);
// 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 mitRangeError: Maximum call stack size exceeded. Speichere den Wert deshalb in einem anderen Feld, z. B.#nameoder_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) einenTypeErroraus. - Ein Setter hat genau einen Parameter. Null oder mehrere Parameter und Rest-Parameter (
...args) sind einSyntaxError. - 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.propentfernt den Setter aus Objektliteralen. Setter von Klassen liegen auf dem Prototyp, deshalb bewirktdeleteauf der Instanz dort nichts.- Kopien per Spread (
{...obj}) oder mitObject.assign()rufen Getter auf und kopieren die Werte. Setter werden dabei nicht übernommen. Accessoren kopierst du mitObject.defineProperties(ziel, Object.getOwnPropertyDescriptors(quelle)). - Klassenfelder (
x = 1;) werden perdefinePropertyauf 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.