9.6 Use cases for Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
helps us with two use cases, if we combine it with Object.defineProperties()
or Object.create()
.
9.6.1 Use case: copying properties into an object
Since ES6, JavaScript already has had 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
:
target[key] = source[key];
That means that it only creates a faithful copy of a property if:
- Its attribute
writable
istrue
and its attributeenumerable
istrue
(because that’s how assignment creates properties). - It is a data property.
The following example illustrates this limitation. Object source
has a setter whose key is data
.
const source = {
set data(value) {
this._data = value;
}
};
// Because there is only a setter, property `data` exists,
// but has the value `undefined`.
assert.equal('data' in source, true);
assert.equal(source.data, undefined);
If we use Object.assign()
to copy property data
, then the accessor property data
is converted to a data property:
const target1 = {};
Object.assign(target1, source);
assert.deepEqual(
Object.getOwnPropertyDescriptor(target1, 'data'),
{
value: undefined,
writable: true,
enumerable: true,
configurable: true,
});
// For comparison, the original:
const desc = Object.getOwnPropertyDescriptor.bind(Object);
assert.deepEqual(
Object.getOwnPropertyDescriptor(source, 'data'),
{
get: undefined,
set: desc(source, 'data').set,
enumerable: true,
configurable: true,
});
Fortunately, using Object.getOwnPropertyDescriptors()
together with Object.defineProperties()
does faithfully copy the property data
:
const target2 = {};
Object.defineProperties(
target2, Object.getOwnPropertyDescriptors(source));
assert.deepEqual(
Object.getOwnPropertyDescriptor(target2, 'data'),
{
get: undefined,
set: desc(source, 'data').set,
enumerable: true,
configurable: true,
});
9.6.1.1 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.
9.6.2 Use case for Object.getOwnPropertyDescriptors(): cloning objects
Shallow cloning is similar to copying properties, which is why Object.getOwnPropertyDescriptors()
is a good choice here, too.
To create the clone, we use Object.create()
:
const original = {
set data(value) {
this._data = value;
}
};
const clone = Object.create(
Object.getPrototypeOf(original),
Object.getOwnPropertyDescriptors(original));
assert.deepEqual(original, clone);
For more information on this topic, see §6 “Copying objects and Arrays”.