Object.getOwnPropertyDescriptors()
本章節說明 ECMAScript 2017 功能「Object.getOwnPropertyDescriptors()
」,由 Jordan Harband 和 Andrea Giammarchi 提出。
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
這表示它無法正確複製具有非預設屬性(取得器、設定器、不可寫入屬性等)的屬性。以下範例說明此限制。物件 source
有一個金鑰為 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
的方法與其家物件(儲存它的物件)緊密連結。目前沒有辦法複製或移動此類方法到不同的物件。