ECMAScript 之取得 Object 的 Property Key
ECMAScript Object 的 Property 基本上是由 Key / Value 構成,連 Method 也是指向 Function 的 Property,我們該如何取得 Object 的 Property Key 做進一步的運用呢 ?
Version
ECMAScript 3
ECMAScript 5.1
ECMAScript 2015
Object.keys()
將 Object 所有 Enumerable Property 的 Key 以 array 傳回,但不包含 Prototype 的 Property
ECMAScript 5.1
至於什麼是 Enumerable Property
呢 ? 稍後會介紹。
1 | var person = { |
以 Object Literal 定義 person
,在 Object Literal 的 property 都是 enumerable,所以 Object.keys()
都能顯示。
- 因為
Object.keys()
回傳為 array,因此能直接使用forEach()
- Object Literal 皆為 Enumerable Property,因此所有 key 都能顯示
1 | function Person(firstName, lastName) { |
ECMAScript 的 OOP 正統寫法,是將 method 定義在 Prototype,但 Object.keys()
無法抓到 Prototype 的 property。
- 將 method 定義在 Prototype
- ㄧ樣使用
Object.keys()
- 但只能顯示 Object 本身的 Enumerable Property,不包含 Prototype 的 Enumerable Property
1 | class Person { |
若使用 ECMAScript 2015 的 class 寫法,Object.keys()
也只能抓到 firstName
與 lastName
,別忘了 class
本質仍是 Constructor Function,其 method 也是定義在 Prototype,因此 Object.keys()
抓不到很合理。
Q : 若要也顯示 Prototype 的 Enumerable Property 呢 ?
要使用 for...in
,稍後會介紹。
Object.getOwnPropertyNames()
將 Object 所有 Property 的 Key 以 array 傳回,包含 Enumerable 與 Non Enumerable Property,但不包含 Prototype 的 Property
ECMAScript 5.1
Object Literal 的 property 都是 Enumerable,所以 Object.keys()
都能使用,但要如何產生 Non Enumerable 的 property 呢 ?
1 | var property = { |
若要特別建立 Non Enumerable Property,就必須使用 Object.create()
,並特別在 Property Object 設定是否為 Enumerable。
第 8 行
1 | lastName: { |
特別設定 lastName
property 的 enumerable
為 false
,則 Object.keys()
將無法顯示 lastName
。
- 將
lastName
的Enumerable
設定為false
- 使用
Object.keys()
- 只顯示
Enumerable
為true
的firstName
與fullName
1 | var property = { |
若改用 Object.getOwnPropertyNames()
,則僅管 lastName
的 Enumerable
為 false
,但 Object.getOwnPropertyNames()
仍然會顯示。
- 將
lastName
的Enumerable
設定為false
- 使用
Object.getOwnPropertyNames()
- 無論
Enumerable
為true
或false
都會顯示
1 | var prototype = { |
將 fullName()
移到 Prototype,而 Object Literal 都是 Enumerable Property。
但因為 Object.getOwnPropertyNames()
不會顯示 Prototype 的 property,因此只能顯示 firstName
與 lastName
。
- 將
fullName()
定義在 Prototype Object.getOwnPropertyNames()
無法顯示 Prototype 的 property
1 | class Person { |
若使用 ECMAScript 2015 的 class 寫法,Object.getOwnPropertyNames()
也只能抓到 firstName
與 lastName
,別忘了 class
本質仍是 Constructor Function,其 method 也是定義在 Prototype,因此 Object.getOwnPropertyNames()
抓不到很合理。
for…in
如同
Object.keys()
將 Object 所有 Enumerable Property 的 Key 以 array 傳回,但包含 Prototype 的 PropertyECMAScript 3
我們發現無論 Object.keys()
或 Object.getOwnPropertyNames()
,都無法顯示 Prototype 的 property,若要連 Prototype 的 property 也一起顯示,則要使用 for...in
。
1 | function Person(firstName, lastName) { |
將 fullName()
定義在 Prototype,之前使用 Object.keys()
或 Object.getOwnPropertyNames()
都無法顯示,但使用 for...in
就可完全顯示了。
- 將
fullName()
定義在 Prototype - 使用
for...in
顯示所有 property 的 key - 連 Prototype 的 property 的 key 也一併顯示
1 | class Person { |
但 for...in
搭配 ECMAScript 2015 的 class
時,卻不會顯示 fullName
。
理論上 class
的 fullName()
是在 Prototype 上,for...in
應該會顯示卻沒顯示,也就是若搭配 class
,for...in
相當於 Object.keys()
,結果比較令人訝異。
簡單來說,能被
Object.keys()
或for in
顯示的 property 就稱為 Enumerable Property,一般 Object Literal、Constructor Function 或 class 寫法的 property,都是 Enumerable Property,若要特別設定為 Non Enumerable Property,則要使用Object.create()
建立 object
Summary
Object.keys() | Object.getOwnPropertyNames() | for in | |
---|---|---|---|
Non Enumerable | No | Yes | No |
Prototype | No | No | Yes |
Object.keys()
最中規中矩,不能顯示 Non Enumerable,也不能顯示 PrototypeObject.getOwnPropertyNames()
有特異功能可顯示 Non Enumerable,但無法顯示 Prototypefor in
有特異功能能顯示 Prototype,但無法顯示 Non Enumerable
Conclusion
- 三種方式都各有其限制,要視需求選擇合適的方式
Object.keys()
與for..in
搭配class
時,竟然結果一樣,比較出乎意外,因為篇幅限制,將令開專文討論之
Reference
MDN, Object.keys()
MDN, Object.getOwnPropertyNames()
MDN, for in