The getOwnPropertyDescriptors() method of the Object object in JavaScript allows us to retrieve all own (non-inherited) property descriptors of an object. By using this method, we can obtain a new object that provides a comprehensive list of descriptors.

Here’s an example to illustrate its usage:

const dog = {}
Object.defineProperties(dog, {
  breed: {
    value: 'Siberian Husky'
  }
})
Object.getOwnPropertyDescriptors(dog)
/*
{
  breed: {
    value: 'Siberian Husky',
    writable: false,
    enumerable: false,
    configurable: false
  }
}
*/

One key use case for this method arises from the limitations of Object.assign(), introduced in ES2015. Object.assign() allows us to copy enumerable own properties from one or more objects and create a new object. However, it fails to correctly copy properties with non-default attributes.

Consider the following object:

const person1 = {
  set name(newName) {
    console.log(newName)
  }
}

Attempting to copy this object using Object.assign() will not work:

const person2 = {}
Object.assign(person2, person1)

However, by using Object.defineProperties() along with Object.getOwnPropertyDescriptors(), we can successfully copy the object and preserve the setter:

const person3 = {}
Object.defineProperties(person3, Object.getOwnPropertyDescriptors(person1))

Let’s run a console test to verify the results:

person1.name = 'x'
// Output: "x"

person2.name = 'x'

person3.name = 'x'
// Output: "x"

As we can see, person2 does not have the setter since it was not copied over correctly.

The same limitation applies when shallow cloning objects with Object.create().