Signatur
Beschreibung
Object.getOwnPropertyDescriptor() liefert ein einfaches Objekt, das die Konfiguration einer Eigenschaft beschreibt. Berücksichtigt werden nur Eigenschaften, die direkt auf dem Objekt definiert sind. Eigenschaften aus der Prototypenkette werden nicht gefunden. Gibt es die Eigenschaft nicht, ist der Rückgabewert undefined.
Es gibt zwei Arten von Deskriptoren:
- Daten-Deskriptor:
value,writable,enumerable,configurable - Accessor-Deskriptor:
get,set,enumerable,configurable
Praktisch ist die Methode vor allem, um Getter und Setter herauszulesen (etwa um sie zu kopieren oder zu umhüllen), um zu prüfen, ob eine Eigenschaft schreibgeschützt oder eingefroren ist, und bei Metaprogrammierung zusammen mit Object.defineProperty() oder in Proxy-Traps.
Das zurückgegebene Objekt ist eine Kopie. Wenn du es änderst, ändert sich die ursprüngliche Eigenschaft nicht. Dafür musst du den geänderten Deskriptor wieder an Object.defineProperty() übergeben.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $obj Pflicht | Object | Das Objekt, auf dem nach der Eigenschaft gesucht wird. Primitive Werte werden seit ES2015 in ein Objekt umgewandelt. null und undefined lösen einen TypeError aus. |
|
| $prop Pflicht | string|symbol | Name oder Symbol der Eigenschaft. Andere Werte werden in einen String umgewandelt. |
Rückgabewert
value/writable bzw. get/set sowie enumerable und configurable. Ist die Eigenschaft nicht direkt auf dem Objekt vorhanden, wird undefined zurückgegeben.Beispiele
Daten-Deskriptor einer normalen Eigenschaft
const user = { name: 'Anna' };
console.log(Object.getOwnPropertyDescriptor(user, 'name'));
Getter aus einer Klasse auslesen
class Temperatur {
#celsius = 20;
get fahrenheit() { return this.#celsius * 9 / 5 + 32; }
}
// Getter liegen auf dem Prototyp, nicht auf der Instanz
const t = new Temperatur();
console.log(Object.getOwnPropertyDescriptor(t, 'fahrenheit'));
const desc = Object.getOwnPropertyDescriptor(Temperatur.prototype, 'fahrenheit');
console.log(typeof desc.get, desc.set, desc.enumerable);
console.log(desc.get.call(t));
Prüfen, ob eine Eigenschaft schreibbar ist
const config = Object.freeze({ apiUrl: 'https://api.example.com' });
const istSchreibbar = (obj, key) => {
const d = Object.getOwnPropertyDescriptor(obj, key);
if (!d) return false;
return 'value' in d ? d.writable : typeof d.set === 'function';
};
console.log(istSchreibbar(config, 'apiUrl'));
console.log(Object.getOwnPropertyDescriptor(config, 'apiUrl'));
Setter umhüllen (Logging)
const konto = {
_saldo: 0,
get saldo() { return this._saldo; },
set saldo(v) { this._saldo = v; }
};
const orig = Object.getOwnPropertyDescriptor(konto, 'saldo');
Object.defineProperty(konto, 'saldo', {
...orig,
set(v) {
console.log(`saldo: ${this._saldo} -> ${v}`);
orig.set.call(this, v);
}
});
konto.saldo = 100;
console.log(konto.saldo);
// Wichtig · Fallstricke
- Nur eigene Eigenschaften: Geerbte Eigenschaften wie Klassen-Getter oder
toStringergebenundefined. Wenn du sie brauchst, musst du selbst mitObject.getPrototypeOf()die Prototypenkette durchlaufen. - Standardwerte: Eigenschaften, die per
Object.defineProperty()angelegt werden, sind ohne ausdrückliche Angabewritable: false,enumerable: falseundconfigurable: false. Bei Eigenschaften, die per Zuweisung entstehen, sind alle dreitrue. - Primitive: In ES5 löste
Object.getOwnPropertyDescriptor('abc', 'length')einenTypeErroraus. Seit ES2015 wird der Wert in ein Objekt umgewandelt, das Ergebnis ist dann{ value: 3, writable: false, enumerable: false, configurable: false }. - Kopie: Wenn du den zurückgegebenen Deskriptor änderst, wirkt sich das nicht auf die Eigenschaft aus.
- Proxy: Bei Proxys wird die Trap
getOwnPropertyDescriptorausgelöst. Sie muss Invarianten einhalten, sonst gibt es einenTypeError. - Mehrere Eigenschaften: Für alle Deskriptoren auf einmal gibt es
Object.getOwnPropertyDescriptors()(ES2017). Damit lassen sich Objekte samt Gettern und Settern kopieren, wasObject.assign()und der Spread-Operator nicht können. - Wird in allen modernen Browsern und in Node.js unterstützt.