ECMAScript 是一個以 Object 與 Function 為主的語言,有別於 Class 為主的 OOP,ECMAScript 有獨特的 Property Descriptor,在 Object.create()
、 Object.defineProperty()
與 Object.getOwnPropertyDescriptor()
可使用。
Version
macOS Catalina 10.15.2
VS Code 1.41.1
Quokka 1.0.268
ECMAScript 5
Object Literal
let book = {
title: 'FP in JavaScript'
}
Object.getOwnPropertyDescriptor(book, 'title') // ?
使用 object literal 建立 plain object,可使用 Object.getOwnPropertyDescriptor()
取得 property 的 property descriptor。
除了 value
外,還多了 3 個 property。
writable
:是否可修改 property,若為false
則為 read-onlyenumerable
:是否可被for...in
loop 與Object.keys()
列舉configurable
:是否可 delete property 或修改writable
、enumerable
與configurable
詳細用法稍後會介紹
Object.create()
let book = Object.create({}, {
title: {
value: 'FP in JavaScript',
writable: true,
enumerable: true,
configurable: true
}
})
Object.getOwnPropertyDescriptor(book, 'title') // ?
Property descriptor 能用在哪呢 ? 若想在建立 object 當下設定其 writable
、enumerable
與 configurable
,可使用 Object.create()
,在其第二個 argument 傳入 property descriptor。
writable
、enumerable
與 configurable
預設皆為 false
,若想如 plain object 一般,則需一開始皆設定為 true
。
Object.defineProperty()
let book = {}
Object.defineProperty(book, 'title', {
value: 'FP in JavaScript',
writable: true,
enumerable: true,
configurable: true
})
Object.getOwnPropertyDescriptor(book, 'title') // ?
若 property 的 writable
、enumerable
與 configurable
無法在 object 建立時決定,可使用 Object.defineProperty()
事後慢慢設定。
Writable
let book = {}
Object.defineProperty(book, 'title', {
value: 'FP in JavaScript',
writable: true,
enumerable: true,
configurable: true
})
Object.getOwnPropertyDescriptor(book, 'title') // ?
若 writable
為 false
,則 property 為 read-only 無法改變。
Enumerable
let book = {}
Object.defineProperty(book, 'title', {
value: 'FP in JavaScript',
writable: true,
enumerable: false,
configurable: true
})
for(let prop in book)
console.log(prop)
Object.keys(book) // ?
若 enumerable
為 false
,則 for...in
loop 與 Object.keys()
都無法使用。
Configurable
let book = {}
Object.defineProperty(book, 'title', {
value: 'FP in JavaScript',
writable: true,
enumerable: true,
configurable: false
})
delete book.title // ?
book // ?
若 configurable
為 false
,則 delete
會失敗回傳 false
。
let book = {}
Object.defineProperty(book, 'title', {
value: 'FP in JavaScript',
writable: true,
enumerable: true,
configurable: false
})
Object.defineProperty(book, 'title', {
value: 'FP in JavaScript',
writable: false,
enumerable: true,
configurable: true
})
Object.getOwnPropertyDescriptor(book, 'title') // ?
若 configurable
為 false
,則無法再使用 Object.defineProperty()
修改 property descriptor。
Conclusion
- 平常使用 property descriptor 機會或許不高,因為 object literal 實在太好用,且又有 constructor function 與 class,但觀念還是要有,如
for...in
loop、Object.keys()
… 等都會用到 property descriptor 觀念
Reference
許國政, 008 天重新認識 JavaScript