Inhaltsverzeichnis
Bitte unterstützen Sie dieses Buch: kaufen Sie es (PDF, EPUB, MOBI) oder spenden Sie
(Werbung, bitte nicht blockieren.)

9. Object.getOwnPropertyDescriptors()

Dieses Kapitel erklärt das ECMAScript 2017-Feature „Object.getOwnPropertyDescriptors()“ von Jordan Harband und Andrea Giammarchi.

9.1 Überblick

Object.getOwnPropertyDescriptors(obj) gibt die Property-Deskriptoren aller eigenen Properties von obj in einem Array zurück.

const obj = {
    [Symbol('foo')]: 123,
    get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));

// Output:
// { [Symbol('foo')]:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

9.2 Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors(obj) nimmt ein Objekt obj und gibt ein Objekt result zurück.

Property-Deskriptoren beschreiben die *Attribute* einer Property (ihren Wert, ob sie beschreibbar ist usw.). Weitere Informationen finden Sie in Abschn. „Property-Attribute und Property-Deskriptoren“ in „Speaking JavaScript“.

Dies ist ein Beispiel für die Verwendung von Object.getOwnPropertyDescriptors()

const obj = {
    [Symbol('foo')]: 123,
    get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));

// Output:
// { [Symbol('foo')]:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

So würden Sie Object.getOwnPropertyDescriptors() implementieren

function getOwnPropertyDescriptors(obj) {
    const result = {};
    for (let key of Reflect.ownKeys(obj)) {
        result[key] = Object.getOwnPropertyDescriptor(obj, key);
    }
    return result;
}

9.3 Anwendungsfälle für Object.getOwnPropertyDescriptors()

9.3.1 Anwendungsfall: Kopieren von Properties in ein Objekt

Seit ES6 verfügt JavaScript bereits über eine Werkzeugmethode zum Kopieren von Properties: Object.assign(). Diese Methode verwendet jedoch einfache Get- und Set-Operationen, um eine Property mit dem Schlüssel key zu kopieren.

const value = source[key]; // get
target[key] = value; // set

Das bedeutet, dass Properties mit nicht standardmäßigen Attributen (Getter, Setter, nicht beschreibbare Properties usw.) nicht korrekt kopiert werden. Das folgende Beispiel veranschaulicht diese Einschränkung. Das Objekt source hat einen Setter mit dem Schlüssel foo.

const source = {
    set foo(value) {
        console.log(value);
    }
};
console.log(Object.getOwnPropertyDescriptor(source, 'foo'));
// { get: undefined,
//   set: [Function: foo],
//   enumerable: true,
//   configurable: true }

Die Verwendung von Object.assign() zum Kopieren der Property foo in das Objekt target schlägt fehl.

const target1 = {};
Object.assign(target1, source);
console.log(Object.getOwnPropertyDescriptor(target1, 'foo'));
// { value: undefined,
//   writable: true,
//   enumerable: true,
//   configurable: true }

Glücklicherweise funktioniert die Verwendung von Object.getOwnPropertyDescriptors() zusammen mit Object.defineProperties().

const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
console.log(Object.getOwnPropertyDescriptor(target2, 'foo'));
// { get: undefined,
//   set: [Function: foo],
//   enumerable: true,
//   configurable: true }

9.3.2 Anwendungsfall: Klonen von Objekten

Flaches Klonen ähnelt dem Kopieren von Properties, weshalb Object.getOwnPropertyDescriptors() auch hier eine gute Wahl ist.

Diesmal verwenden wir Object.create(), das zwei Parameter hat.

const clone = Object.create(Object.getPrototypeOf(obj),
    Object.getOwnPropertyDescriptors(obj));

9.3.3 Anwendungsfall: Plattformübergreifende Objektliterale mit beliebigen Prototypen

Die syntaktisch schönste Möglichkeit, ein Objektliteral zum Erstellen eines Objekts mit einem beliebigen Prototyp prot zu verwenden, ist die Verwendung der speziellen Property __proto__.

const obj = {
    __proto__: prot,
    foo: 123,
};

Leider ist garantiert, dass diese Funktion nur in Browsern vorhanden ist. Die übliche Problemumgehung ist Object.create() und Zuweisung.

const obj = Object.create(prot);
obj.foo = 123;

Aber Sie können auch Object.getOwnPropertyDescriptors() verwenden.

const obj = Object.create(
    prot,
    Object.getOwnPropertyDescriptors({
        foo: 123,
    })
);

Eine weitere Alternative ist Object.assign().

const obj = Object.assign(
    Object.create(prot),
    {
        foo: 123,
    }
);

9.4 Fallstrick: Kopieren von Methoden, die super verwenden

Eine Methode, die super verwendet, ist fest mit ihrem *Home-Objekt* (dem Objekt, in dem sie gespeichert ist) verbunden. Derzeit gibt es keine Möglichkeit, eine solche Methode auf ein anderes Objekt zu kopieren oder zu verschieben.

Weiter: 10. Nachgestellte Kommas in Parameterlisten und Aufrufen von Funktionen