阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors()

作者:陈川 阅读数:41682人阅读 分类: JavaScript

Object.getOwnPropertyDescriptors() 是 ECMAScript 8(ES2017)引入的一个静态方法,用于获取对象所有自身属性的描述符。与 Object.getOwnPropertyDescriptor() 不同,它一次性返回对象的所有属性描述符,包括可枚举和不可枚举属性。这一特性在对象复制、属性代理等场景中非常实用。

基本语法与返回值

方法签名如下:

Object.getOwnPropertyDescriptors(obj)
  • 参数obj 是目标对象。
  • 返回值:一个包含所有自身属性描述符的对象,键为属性名,值为属性描述符对象(即 {value, writable, enumerable, configurable}{get, set, enumerable, configurable})。

示例:获取普通对象的属性描述符

const obj = {
  name: 'Alice',
  age: 30,
  get greeting() {
    return `Hello, ${this.name}!`;
  }
};

const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors);
// 输出:
// {
//   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 }
// }

Object.getOwnPropertyDescriptor() 的区别

Object.getOwnPropertyDescriptor() 只能获取单个属性的描述符,而 Object.getOwnPropertyDescriptors() 一次性返回所有属性的描述符。例如:

const singleDescriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(singleDescriptor); // { value: 'Alice', writable: true, enumerable: true, configurable: true }

实际应用场景

1. 深度复制对象属性

传统的 Object.assign() 只能复制可枚举属性和值,无法复制属性的描述符(如 getter/setter)。结合 Object.defineProperties() 可以实现完整复制:

const source = {
  _id: 1,
  get id() {
    return this._id;
  }
};

const shallowCopy = Object.assign({}, source);
console.log(Object.getOwnPropertyDescriptor(shallowCopy, 'id')); // { value: 1, ... } (getter 丢失)

// 使用描述符复制
const deepCopy = Object.create(
  Object.getPrototypeOf(source),
  Object.getOwnPropertyDescriptors(source)
);
console.log(Object.getOwnPropertyDescriptor(deepCopy, 'id')); // { get: [Function: id], ... } (保留 getter)

2. 创建不可变对象

通过描述符可以精确控制对象的可写性:

const immutable = Object.defineProperties(
  {},
  Object.getOwnPropertyDescriptors({
    key: 'value',
    get readOnly() {
      return 'constant';
    }
  })
);

Object.freeze(immutable); // 进一步冻结对象

3. 混入(Mixin)模式

在组合多个对象的属性时,保留完整的属性特性:

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

处理 Symbol 属性

该方法同样支持 Symbol 类型的属性键:

const symbolKey = Symbol('private');
const obj = {
  [symbolKey]: 'secret',
  public: 'info'
};

console.log(Object.getOwnPropertyDescriptors(obj));
// 输出:
// {
//   public: { value: 'info', writable: true, enumerable: true, configurable: true },
//   [Symbol(private)]: { value: 'secret', writable: true, enumerable: true, configurable: true }
// }

与 Proxy 结合使用

在代理对象中,可以通过描述符实现高级属性控制:

const handler = {
  getOwnPropertyDescriptor(target, prop) {
    const desc = Object.getOwnPropertyDescriptor(target, prop);
    if (prop.startsWith('_')) {
      return { ...desc, enumerable: false }; // 隐藏以下划线开头的属性
    }
    return desc;
  }
};

const target = { _hidden: 'value', visible: 'text' };
const proxy = new Proxy(target, handler);

console.log(Object.getOwnPropertyDescriptors(proxy));
// 输出中 _hidden 的 enumerable 被改为 false

浏览器兼容性与 Polyfill

现代主流浏览器均支持该方法,但对于旧环境可以通过以下 Polyfill 实现:

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

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌