Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
is a static method introduced in ECMAScript 8 (ES2017) that retrieves the descriptors of all an object's own properties. Unlike Object.getOwnPropertyDescriptor()
, it returns the descriptors of all properties at once, including both enumerable and non-enumerable properties. This feature is particularly useful in scenarios like object copying and property proxying.
Basic Syntax and Return Value
The method signature is as follows:
Object.getOwnPropertyDescriptors(obj)
- Parameter:
obj
is the target object. - Return value: An object containing the descriptors of all own properties, where the keys are property names and the values are property descriptor objects (i.e.,
{value, writable, enumerable, configurable}
or{get, set, enumerable, configurable}
).
Example: Getting Property Descriptors of a Plain Object
const obj = {
name: 'Alice',
age: 30,
get greeting() {
return `Hello, ${this.name}!`;
}
};
const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// Output:
// {
// name: { value: 'Alice', writable: true, enumerable: true, configurable: true },
// age: { value: 30, writable: true, enumerable: true, configurable: true },
// greeting: { get: [Function: greeting], set: undefined, enumerable: true, configurable: true }
// }
Difference from Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor()
retrieves the descriptor of a single property, while Object.getOwnPropertyDescriptors()
returns the descriptors of all properties at once. For example:
const singleDescriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(singleDescriptor); // { value: 'Alice', writable: true, enumerable: true, configurable: true }
Practical Use Cases
1. Deep Copying Object Properties
Traditional Object.assign()
only copies enumerable properties and their values, failing to copy property descriptors (e.g., getter
/setter
). Combining with Object.defineProperties()
enables complete copying:
const source = {
_id: 1,
get id() {
return this._id;
}
};
const shallowCopy = Object.assign({}, source);
console.log(Object.getOwnPropertyDescriptor(shallowCopy, 'id')); // { value: 1, ... } (getter lost)
// Using descriptors for copying
const deepCopy = Object.create(
Object.getPrototypeOf(source),
Object.getOwnPropertyDescriptors(source)
);
console.log(Object.getOwnPropertyDescriptor(deepCopy, 'id')); // { get: [Function: id], ... } (getter preserved)
2. Creating Immutable Objects
Descriptors allow precise control over an object's writability:
const immutable = Object.defineProperties(
{},
Object.getOwnPropertyDescriptors({
key: 'value',
get readOnly() {
return 'constant';
}
})
);
Object.freeze(immutable); // Further freeze the object
3. Mixin Pattern
When combining properties from multiple objects, retain complete property attributes:
const mixin = (target, ...sources) => {
sources.forEach(source => {
Object.defineProperties(
target,
Object.getOwnPropertyDescriptors(source)
);
});
return target;
};
const objA = { get data() { return 42; } };
const objB = { log() { console.log(this.data); } };
const mixed = mixin({}, objA, objB);
mixed.log(); // 42
Handling Symbol Properties
The method also supports Symbol property keys:
const symbolKey = Symbol('private');
const obj = {
[symbolKey]: 'secret',
public: 'info'
};
console.log(Object.getOwnPropertyDescriptors(obj));
// Output:
// {
// public: { value: 'info', writable: true, enumerable: true, configurable: true },
// [Symbol(private)]: { value: 'secret', writable: true, enumerable: true, configurable: true }
// }
Combining with Proxy
In proxy objects, descriptors can be used to implement advanced property control:
const handler = {
getOwnPropertyDescriptor(target, prop) {
const desc = Object.getOwnPropertyDescriptor(target, prop);
if (prop.startsWith('_')) {
return { ...desc, enumerable: false }; // Hide properties starting with underscore
}
return desc;
}
};
const target = { _hidden: 'value', visible: 'text' };
const proxy = new Proxy(target, handler);
console.log(Object.getOwnPropertyDescriptors(proxy));
// The output shows _hidden's enumerable set to false
Browser Compatibility and Polyfill
Modern mainstream browsers support this method, but for older environments, the following polyfill can be used:
if (!Object.getOwnPropertyDescriptors) {
Object.getOwnPropertyDescriptors = function(obj) {
const result = {};
for (const key of Reflect.ownKeys(obj)) {
result[key] = Object.getOwnPropertyDescriptor(obj, key);
}
return result;
};
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn