您的位置:首页 » 分类: JavaScript & ES2015 (ES6) » 文章: ES2017 中的 Object.getOwnPropertyDescriptors()

ES2017 中的 Object.getOwnPropertyDescriptors()

小编推荐:掘金是一个高质量的技术社区,从 ECMAScript 6 到 Vue.js,性能优化到开源类库,让你不错过前端开发的每一个技术干货。各大应用市场搜索「掘金」即可下载APP,技术干货尽在掌握..

本章介绍了 ECMAScript 2017 的 Object.getOwnPropertyDescriptors() 特性 。

概述

Object.getOwnPropertyDescriptors(obj) 返回指定对象 obj 上自有属性对应的属性描述符:

const obj = {
    [Symbol('foo')]: 123,
    get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));

// Output:
// { [Symbol('foo')]:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors(obj) 接受一个 obj对象 并返回一个 result 结果对象:

  • 对于 obj 的每个 自有(非继承的)属性,它会添加一个属性,其结果的键是相同的,其值是obj属性的描述符。

属性描述符描述属性的一些 特征(attributes)(其值,是否可写等)。有关更多信息,请参阅 Sect 。“Speaking JavaScript” 中的 “属性 特征(attributes) 和 属性描述符”。

这是使用 Object.getOwnPropertyDescriptors() 的一个例子:

const obj = {
    [Symbol('foo')]: 123,
    get bar() { return 'abc' },
};
console.log(Object.getOwnPropertyDescriptors(obj));

// Output:
// { [Symbol('foo')]:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

这是 Object.getOwnPropertyDescriptors() 的实现:

function getOwnPropertyDescriptors(obj) {
    const result = {};
    for (let key of Reflect.ownKeys(obj)) {
        result[key] = Object.getOwnPropertyDescriptor(obj, key);
    }
    return result;
}

Object.getOwnPropertyDescriptors() 的用例

用例:拷贝属性到一个对象中

自 ES6 起,JavaScript 已经有复制属性的工具方法了:Object.assign() 。但是,该方法使用了简单的 getset 操作来复制其键为 key 的属性:

const value = source[key]; // get
target[key] = value; // set

这意味着它不能正确地复制具有非默认特征(attributes)的属性(getter,setter,不可写属性,等)。以下示例说明了此限制。对象 source 有一个 setter ,其键是 foo

const source = {
    set foo(value) {
        console.log(value);
    }
};
console.log(Object.getOwnPropertyDescriptor(source, 'foo'));
// { get: undefined,
//   set: [Function: foo],
//   enumerable: true,
//   configurable: true }

使用 Object.assign() 将属性 foo 复制到对象 target 则失败了:

const target1 = {};
Object.assign(target1, source);
console.log(Object.getOwnPropertyDescriptor(target1, 'foo'));
// { value: undefined,
//   writable: true,
//   enumerable: true,
//   configurable: true }

幸运的是,使用 Object.getOwnPropertyDescriptors()Object.defineProperties() 可以一起工作:

const target2 = {};
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
console.log(Object.getOwnPropertyDescriptor(target2, 'foo'));
// { get: undefined,
//   set: [Function: foo],
//   enumerable: true,
//   configurable: true }

用例:克隆对象

浅拷贝(浅克隆)类似于复制属性,这里 Object.getOwnPropertyDescriptors() 也是一个很好的选择。

这次,我们使用 Object.create() ,它有两个参数:

  • 第一个参数指定它返回对象的原型。
  • 可选的第二个参数是类似于 Object.getOwnPropertyDescriptors() 返回的属性描述符集合。
const clone = Object.create(Object.getPrototypeOf(obj),
    Object.getOwnPropertyDescriptors(obj));

用例:带有任意原型的跨平台对象字面量

要使用对象字面量创建带有任意原型 prot 的对象,语法最好的方法是使用特殊属性 __proto__

const obj = {
    __proto__: prot,
    foo: 123,
};

遗憾的是,这个特性只能保证在浏览器里运行。 常见的解决方法是 Object.create() 和赋值:

const obj = Object.create(prot);
obj.foo = 123;

但是现在你也可以使用 Object.getOwnPropertyDescriptors()

const obj = Object.create(
    prot,
    Object.getOwnPropertyDescriptors({
        foo: 123,
    })
);

另一种方法是使用 Object.assign()

const obj = Object.assign(
    Object.create(prot),
    {
        foo: 123,
    }
);

陷阱:拷贝使用 super 的方法

使用 super 的方法与其 home 对象(存储该方法的对象)是强关联的。目前没有办法将这种方法复制或移动到不同的对象中。

原文链接:http://exploringjs.com/es2016-es2017/ch_object-getownpropertydescriptors.html

正文完。下面还有一个推广让最好的人才遇见更好的机会!

互联网行业的年轻人,他们面对着怎样的职业瓶颈、困惑与未来选择?过去,这鲜有人关心。资深的职场人,也多半优先选择熟人去推荐机会。

100offer致力于改变现状,帮互联网行业最好的人才发现更好的机会。使用 100offer.com 或 100offer App ,可以一周内获得中国、美国等数千家优质企业的工作机会。

马上去遇见更好的机会
推广结束

关注WEB前端开发官方公众号

关注国内外最新最好的前端开发技术干货,获取最新前端开发资讯,致力于打造高质量的前端技术分享公众号

发表评论

电子邮件地址不会被公开。 必填项已用*标注