Start · Sprachen · JavaScript · Referenz · Reflect.defineProperty()

Reflect.defineProperty()

Methode

Definiert oder ändert eine Eigenschaft auf einem Objekt wie <code>Object.defineProperty()</code>, gibt aber <code>true</code> oder <code>false</code> zurück, statt eine Ausnahme zu werfen.

seit JavaScript ES2015 Kategorie: method-property

Signatur

Reflect.defineProperty(target, propertyKey, attributes)

Beschreibung

Reflect.defineProperty() legt eine neue Eigenschaft direkt auf einem Objekt an oder ändert eine vorhandene. Dafür gibt man einen Eigenschafts-Deskriptor an, also ein Objekt mit value, writable, enumerable, configurable bzw. get/set. Die Methode funktioniert genauso wie Object.defineProperty().

Der wichtige Unterschied liegt im Rückgabewert: Object.defineProperty() gibt das Objekt zurück und wirft einen TypeError, wenn die Definition fehlschlägt, etwa bei einer nicht konfigurierbaren Eigenschaft oder einem nicht erweiterbaren Objekt. Reflect.defineProperty() gibt dagegen einfach true bei Erfolg und false bei Misserfolg zurück. Deshalb kann man den Erfolg mit einem normalen if prüfen und braucht kein try/catch.

Besonders nützlich ist die Methode in Proxy-Handlern: Die Falle defineProperty muss einen Wahrheitswert zurückgeben, und Reflect.defineProperty() liefert genau diesen Wert, wenn man an das Standardverhalten weiterleitet. Auch in Bibliotheken, die Objekte defensiv verändern, macht der boolesche Rückgabewert den Code übersichtlicher.

Parameter

Name Typ Default Beschreibung
$target Pflicht object Das Zielobjekt, auf dem die Eigenschaft definiert werden soll. Ist es kein Objekt, wird ein TypeError geworfen.
$propertyKey Pflicht string|symbol Name der Eigenschaft, die definiert oder geändert werden soll. Andere Werte werden in einen String umgewandelt.
$attributes Pflicht object Eigenschafts-Deskriptor mit value, writable, get, set, enumerable und configurable. Fehlende Attribute gelten bei neuen Eigenschaften als false bzw. undefined.

Rückgabewert

Typ
boolean
Beschreibung
true, wenn die Eigenschaft erfolgreich definiert wurde, sonst false.

Beispiele

Einfache Eigenschaft definieren und Erfolg prüfen

const config = {};

const ok = Reflect.defineProperty(config, 'version', {
  value: '1.0.0',
  writable: false,
  enumerable: true,
  configurable: false
});

console.log(ok);
console.log(config.version);
true 1.0.0

Fehlschlag ohne try/catch erkennen

const frozen = Object.freeze({ id: 42 });

if (!Reflect.defineProperty(frozen, 'name', { value: 'Test' })) {
  console.log('Eigenschaft konnte nicht angelegt werden');
}

// Zum Vergleich: Object.defineProperty wirft
try {
  Object.defineProperty(frozen, 'name', { value: 'Test' });
} catch (err) {
  console.log(err.constructor.name);
}
Eigenschaft konnte nicht angelegt werden TypeError

Proxy-Falle mit Validierung

const user = {};

const guarded = new Proxy(user, {
  defineProperty(target, key, descriptor) {
    if (key.toString().startsWith('_')) {
      console.log(`Private Eigenschaft ${String(key)} abgelehnt`);
      return false;
    }
    // An Standardverhalten weiterleiten, liefert boolean
    return Reflect.defineProperty(target, key, descriptor);
  }
});

console.log(Reflect.defineProperty(guarded, 'name', { value: 'Anna', enumerable: true }));
console.log(Reflect.defineProperty(guarded, '_secret', { value: 'x' }));
console.log(Object.keys(user));
true Private Eigenschaft _secret abgelehnt false [ 'name' ]

Getter als berechnete Eigenschaft

const rect = { width: 4, height: 3 };

Reflect.defineProperty(rect, 'area', {
  get() {
    return this.width * this.height;
  },
  enumerable: false,
  configurable: true
});

rect.width = 10;
console.log(rect.area);
console.log(Object.keys(rect));
30 [ 'width', 'height' ]

// Wichtig · Fallstricke

  • Nicht jeder Fehler ergibt false: Ist target kein Objekt (z. B. null oder ein primitiver Wert), wirft die Methode trotzdem einen TypeError. Das gilt auch für einen ungültigen Deskriptor, der zum Beispiel value und get gleichzeitig enthält.
  • Standardwerte beachten: Bei neuen Eigenschaften sind writable, enumerable und configurable standardmäßig false. Das ist anders als bei einer einfachen Zuweisung (obj.x = 1), bei der alle drei true sind.
  • Eine nicht konfigurierbare Eigenschaft lässt sich nicht mehr umdefinieren oder löschen. Die einzige Ausnahme: writable darf von true auf false gesetzt werden.
  • In Proxy-Fallen muss das Ergebnis die Invarianten des Zielobjekts einhalten. Andernfalls wirft die Engine einen TypeError, auch wenn die Falle true zurückgibt.
  • Kompatibilität: Wird von allen modernen Browsern und von Node.js ab Version 6 unterstützt. Nicht verfügbar im Internet Explorer.