Free email newsletter: “ News


ES proposal: Object.getOwnPropertyDescriptors()

The ECMAScript proposal “Object.getOwnPropertyDescriptors()” by Jordan Harband and Andrea Giammarchi is part of ECMAScript 2017. This blog post explains it.


Object.getOwnPropertyDescriptors(obj) accepts an object obj and returns an object result:

  • For each own (non-inherited) property of obj, it adds a property to result whose key is the same and whose value is the the former property’s descriptor.

Property descriptors describe the attributes of a property (its value, whether it is writable, etc.). For more information, consult Sect. “Property Attributes and Property Descriptors” in “Speaking JavaScript”.

This is an example of using Object.getOwnPropertyDescriptors():

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

This is how you would implement Object.getOwnPropertyDescriptors():

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

Use cases for Object.getOwnPropertyDescriptors()

Use case: copying properties into an object

Since ES6, JavaScript already has a tool method for copying properties: Object.assign(). However, this method uses simple get and set operations to copy a property whose key is key:

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

That means that it doesn’t properly copy properties with non-default attributes (getters, setters, non-writable properties, etc.). The following example illustrates this limitation. The object source has a getter whose key is foo:

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

Using Object.assign() to copy property foo to object target fails:

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

Fortunately, using Object.getOwnPropertyDescriptors() together with Object.defineProperties() works:

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

Use case: cloning objects

Shallow cloning is similar to copying properties, which is why Object.getOwnPropertyDescriptors() is a good choice here, too.

This time, we use Object.create() that has two parameters:

  • The first parameter specifies the prototype of the object it returns.
  • The optional second parameter is a property descriptor collection like the ones returned by Object.getOwnPropertyDescriptors().
    const clone = Object.create(Object.getPrototypeOf(obj),

Use case: cross-platform object literals with arbitrary prototypes

The syntactically nicest way of using an object literal to create an object with an arbitrary prototype prot is to use the special property __proto__:

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

Alas, that feature is only guaranteed to be there in browsers. The common work-around is Object.create() and assignment:

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

But you can also use Object.getOwnPropertyDescriptors():

    const obj = Object.create(
            foo: 123,

Another alternative is Object.assign():

    const obj = Object.assign(
            foo: 123,

Pitfall: copying methods that use super

A method that uses super is firmly connected with its home object (the object it is stored in). There is currently no way to copy or move such a method to a different object.

Further reading

JavaScript design process:

Object.getOwnPropertyDescriptors() and property descriptors:

No comments: