Signatur
Beschreibung
Reflect.getOwnPropertyDescriptor() liest den vollständigen Deskriptor einer eigenen (nicht geerbten) Eigenschaft aus. Das Ergebnis ist ein Objekt mit den Feldern value, writable, enumerable und configurable (Daten-Eigenschaft) bzw. get, set, enumerable und configurable (Accessor-Eigenschaft).
Die Methode verhält sich fast genauso wie Object.getOwnPropertyDescriptor(). Der wichtige Unterschied: Ist target kein Objekt (etwa ein String oder eine Zahl), wirft Reflect.getOwnPropertyDescriptor() einen TypeError, während Object.getOwnPropertyDescriptor() den primitiven Wert seit ES2015 stillschweigend in ein Objekt umwandelt.
Ihr Haupteinsatzgebiet ist die Arbeit mit Proxy: In der Trap getOwnPropertyDescriptor leitet man mit Reflect.getOwnPropertyDescriptor(target, prop) das Standardverhalten sauber an das Zielobjekt weiter. Außerdem eignet sie sich für Metaprogrammierung, z. B. um zu prüfen, ob eine Eigenschaft schreibgeschützt ist oder einen Getter besitzt, bevor man sie kopiert oder verändert.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $target Pflicht | object | Das Zielobjekt, auf dem die eigene Eigenschaft gesucht wird. Muss ein Objekt sein, sonst wird ein TypeError geworfen. |
|
| $propertyKey Pflicht | string|symbol | Name oder Symbol der Eigenschaft. Andere Werte werden in einen String umgewandelt. |
Rückgabewert
{ value, writable, enumerable, configurable } oder { get, set, enumerable, configurable }), wenn die Eigenschaft als eigene Eigenschaft existiert, sonst undefined.Beispiele
Deskriptor einer Daten- und einer Accessor-Eigenschaft lesen
const user = {
name: 'Anna',
get greeting() {
return `Hallo ${this.name}`;
}
};
console.log(Reflect.getOwnPropertyDescriptor(user, 'name'));
console.log(Reflect.getOwnPropertyDescriptor(user, 'greeting'));
console.log(Reflect.getOwnPropertyDescriptor(user, 'toString')); // geerbt
Prüfen, ob eine Eigenschaft schreibgeschützt ist
const config = {};
Object.defineProperty(config, 'apiUrl', {
value: 'https://api.example.com',
writable: false,
enumerable: true,
configurable: false
});
const isReadOnly = (obj, key) => {
const desc = Reflect.getOwnPropertyDescriptor(obj, key);
if (!desc) return false;
return 'value' in desc ? !desc.writable : desc.set === undefined;
};
console.log(isReadOnly(config, 'apiUrl'));
console.log(isReadOnly({ port: 8080 }, 'port'));
Proxy-Trap: private Felder verbergen
const account = { owner: 'Ben', _secret: 'pin-1234' };
const safe = new Proxy(account, {
getOwnPropertyDescriptor(target, prop) {
if (typeof prop === 'string' && prop.startsWith('_')) {
return undefined; // Eigenschaft wirkt nicht vorhanden
}
return Reflect.getOwnPropertyDescriptor(target, prop);
}
});
console.log(Object.getOwnPropertyDescriptor(safe, 'owner')?.value);
console.log(Object.getOwnPropertyDescriptor(safe, '_secret'));
Unterschied zu Object.getOwnPropertyDescriptor bei Primitiven
console.log(Object.getOwnPropertyDescriptor('abc', 'length'));
try {
Reflect.getOwnPropertyDescriptor('abc', 'length');
} catch (err) {
console.log(err.constructor.name);
}
// Wichtig · Fallstricke
- Nur eigene Eigenschaften: Geerbte Eigenschaften aus der Prototypkette liefern
undefined. Um sie zu finden, muss man die Kette mitReflect.getPrototypeOf()selbst durchlaufen. - Kein Objekt →
TypeError: Anders alsObject.getOwnPropertyDescriptor()werden Primitive nicht umgewandelt. Das ist gewollt und macht Fehler früher sichtbar. - Proxy-Invarianten: Eine
getOwnPropertyDescriptor-Trap darf eine nicht-konfigurierbare Eigenschaft des Ziels nicht als fehlend melden und auch keine Eigenschaft auf einem nicht-erweiterbaren Ziel erfinden. Bei Verstoß wirft die Engine einenTypeError. - Der zurückgegebene Deskriptor ist eine Kopie; Änderungen daran wirken sich nicht auf das Objekt aus. Zum Setzen dient
Reflect.defineProperty(). - Kompatibilität: in allen modernen Browsern und seit Node.js 6 verfügbar; nicht im Internet Explorer.