Start · Sprachen · JavaScript · Referenz · Object.prototype.__defineSetter__()

Object.prototype.__defineSetter__()

Methode

Bindet eine Eigenschaft eines Objekts an eine Setter-Funktion, die bei jeder Zuweisung an diese Eigenschaft aufgerufen wird. Veraltet, stattdessen <code>Object.defineProperty()</code> verwenden.

seit JavaScript ES2017 (Annex B, standardisiert als Legacy-Feature deprecated seit ja Kategorie: method-property

Signatur

Object.prototype.__defineSetter__(prop, func)

Beschreibung

__defineSetter__() legt auf dem Objekt, auf dem die Methode aufgerufen wird, eine Accessor-Eigenschaft an (oder ändert eine vorhandene). Jede spätere Zuweisung wie obj.prop = wert ruft dann die übergebene Funktion auf. Der zugewiesene Wert wird ihr als einziges Argument übergeben, this zeigt auf das Objekt.

Die Methode stammt aus der Zeit vor ES5. Damals gab es noch kein Object.defineProperty() und keine set-Syntax in Objektliteralen. Heute ist sie nur noch im Anhang B der Spezifikation (Legacy-Features für Web-Browser) festgehalten und gilt als veraltet. Neuer Code sollte stattdessen die set-Syntax in Objektliteralen und Klassen oder Object.defineProperty() verwenden.

Intern entspricht der Aufruf ungefähr Object.defineProperty(obj, prop, { set: func, enumerable: true, configurable: true }). Ein bereits vorhandener Getter derselben Eigenschaft bleibt dabei erhalten. War die Eigenschaft dagegen eine Dateneigenschaft, geht ihr bisheriger Wert verloren.

Parameter

Name Typ Default Beschreibung
$prop Pflicht string | symbol Name der Eigenschaft, an die der Setter gebunden wird. Andere Werte werden in einen Eigenschaftsschlüssel umgewandelt.
$func Pflicht Function Funktion, die bei einer Zuweisung an prop aufgerufen wird. Sie bekommt den zugewiesenen Wert als Argument (function (val) { … }). Ist func nicht aufrufbar, wird ein TypeError ausgelöst.

Rückgabewert

Typ
undefined
Beschreibung
Gibt nichts zurück (undefined). Das Objekt selbst wird verändert.

Beispiele

Setter mit Validierung (Legacy-Stil)

const konto = { _saldo: 0 };

konto.__defineSetter__('saldo', function (wert) {
  if (typeof wert !== 'number' || Number.isNaN(wert)) {
    throw new TypeError('Saldo muss eine Zahl sein');
  }
  this._saldo = Math.round(wert * 100) / 100;
});
konto.__defineGetter__('saldo', function () {
  return this._saldo;
});

konto.saldo = 19.999;
console.log(konto.saldo);

try {
  konto.saldo = 'viel';
} catch (e) {
  console.log(e.message);
}
20 Saldo muss eine Zahl sein

Moderne Entsprechung mit set-Syntax und Object.defineProperty()

// 1. Setter direkt im Objektliteral
const nutzer = {
  _name: '',
  set name(wert) {
    this._name = String(wert).trim();
  },
  get name() {
    return this._name;
  }
};
nutzer.name = '  Anna  ';
console.log(nutzer.name);

// 2. Setter nachträglich hinzufügen
const protokoll = [];
const config = {};
Object.defineProperty(config, 'modus', {
  set(wert) { protokoll.push(`modus -> ${wert}`); },
  enumerable: true,
  configurable: true
});
config.modus = 'dark';
console.log(protokoll);
Anna [ 'modus -> dark' ]

Setter prüfen und Nur-Setter-Falle

const obj = {};
obj.__defineSetter__('x', (v) => console.log('gesetzt:', v));

obj.x = 42;
// Ohne Getter liefert das Lesen undefined
console.log(obj.x);

// Setter wieder auslesen
console.log(typeof obj.__lookupSetter__('x'));
console.log(Object.getOwnPropertyDescriptor(obj, 'x'));
gesetzt: 42 undefined function { get: undefined, set: [Function (anonymous)], enumerable: true, configurable: true }

// Wichtig · Fallstricke

  • Veraltet: Die Methode ist nur in Anhang B von ECMAScript spezifiziert. Sie funktioniert in allen gängigen Browsern und in Node.js, sollte in neuem Code aber durch die set-Syntax oder Object.defineProperty() ersetzt werden.
  • Nicht überall verfügbar: Objekte ohne Prototyp (Object.create(null)) erben die Methode nicht. Ein Aufruf wirft dort einen TypeError. Auch manche Linter- und Sicherheitsrichtlinien verbieten ihre Nutzung.
  • Nur Setter, kein Getter: Wird kein Getter definiert, liefert das Lesen der Eigenschaft undefined. Der vorherige Wert einer Dateneigenschaft wird überschrieben.
  • Endlosrekursion: Weist der Setter selbst this.prop zu (dieselbe Eigenschaft), ruft er sich endlos selbst auf und es kommt zu einem RangeError. Speichere den Wert daher in einem anderen Feld (z. B. _prop) oder in einer Closure.
  • Arrow-Funktionen: Sie haben kein eigenes this. Wenn der Setter auf das Objekt zugreifen soll, verwende eine normale function.
  • Ist die Eigenschaft nicht konfigurierbar (z. B. nach Object.freeze()) oder das Objekt nicht erweiterbar, wird ein TypeError ausgelöst.