Object.getOwnPropertyDescriptors()
本章解释了由 Jordan Harband 和 Andrea Giammarchi 提出的 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
的每个自身(非继承)属性,它都会向 result
添加一个属性,该属性的键相同,其值为前一个属性的*描述符*。属性描述符描述了属性的*特性*(其值、是否可写等)。有关更多信息,请参阅“Speaking JavaScript”中的“属性特性和属性描述符”一节。
以下是使用 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()
。但是,此方法使用简单的获取和设置操作来复制键为 key
的属性。
const
value
=
source
[
key
];
// get
target
[
key
]
=
value
;
// set
这意味着它无法正确复制具有非默认属性(getter、setter、不可写属性等)的属性。以下示例说明了此限制。对象 source
有一个键为 foo
的 setter。
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
的方法与其*宿主对象*(存储它的对象)紧密相连。目前还没有办法将这样的方法复制或移动到不同的对象。