阿里云主机折上折
  • 微信号
Current Site:Index > Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors()

Author:Chuan Chen 阅读数:41683人阅读 分类: JavaScript

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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.