Getter Property 讓我們可兼具 Function 的靈活與 Property 的方便,且其 Lazy 特性在一些需要 CPU 運算場合可延遲執行增進效率。
Version
macOS Catalina 10.15.2
VS Code 1.41.1
Quokka 1.0.267
ECMAScript 2015
Getter Function
let book = {
data: [
{ title: 'FP in JavaScript', price: 100 }
],
getTitle: function() {
return this.data[0].title
},
setTitle: function(v) {
this.data[0].title = v
}
}
book.setTitle('Speaking JavaScript')
book.getTitle() // ?
Object 若想提供 property,卻又想如 function 般有彈性,過去只能透過 function 提供 getter 與 setter。
但也由於是 function,因此使用上並不如 property 直覺。
Getter Property
let book = {
data: [
{ title: 'FP in JavaScript', price: 100 }
],
get title() {
return this.data[0].title
},
set title(v) {
this.data[0].title = v
}
}
book.title = 'Speaking JavaScript'
book.title // ?
ECMAScript 另外提供了 getter / setter property,只要在 function 前面加上 get
與 set
,就可得到 function 的彈性與 property 的直覺。
Computed Property Names
let book = {
data: [
{ title: 'FP in JavaScript', price: 100 }
],
get ['title']() {
return this.data[0].title
},
set ['title'](v) {
this.data[0].title = v
}
}
book.title = 'Speaking JavaScript'
book.title // ?
ES6 支援了 computed property name,也能用在 getter property。
Class
class Book {
constructor() {
this.data = [
{ title: 'FP in JavaScript', price: 100 }
]
}
get title() {
return this.data[0].title
}
set title(v) {
this.data[0].title = v
}
}
let book = new Book
book.title = 'Speaking JavaScript'
book.title // ?
ES6 的 class 也能使用 getter / setter property。
Object.defineProperty()
let book = {
data: [
{ title: 'FP in JavaScript', price: 100 }
]
}
Object.defineProperty(book, 'title', {
get: function() { return this.data[0].title },
set: function(v) { this.data[0].title = v }
})
book.title = 'Speaking JavaScript'
book.title // ?
Getter property 只能在 object 或 class 事先定義,若想在 object 建立後才動態新增 getter property,就要改用 Object.defineProperty()
。
Summary
class Book {
constructor() {
this.data = [
{ title: 'FP in JavaScript', price: 100 }
]
}
get title() {
return this.data[0].title
}
set title(v) {
this.data[0].title = v
}
}
let book = new Book
Object.defineProperty(book, 'price', {
get: function() { return this.data[0].price },
set: function(v) { this.data[0].price = v }
})
book.hasOwnProperty('title') // ?
book.hasOwnProperty('price') // ?
Getter property 與 Object.defineProperty()
若用在 object 則等效,但若用於 class 時則不太一樣。
Class 的 getter property 會建立在 object 的 prototype 上,但 Object.defineProperty()
則直接建立在 object 上,可使用 hasOwnProperty()
證明。
Lazy Getter
Getter Property 與傳統 Property 用起來感覺一樣,但何時該使用呢 ? MDN 提供了以下幾點建議:
- 當 property 非常耗 CPU 時,使用 getter property 讓 property 延後到要使用才產生
- 該 property 很少使用,可考慮要使用時再產生即可
- 該 property 經常使用,可考慮 cache 下來,只有 getter property 第一次需正常運算,之後都使用 cache 版本
Conclusion
- Getter property 讓我們同時擁有 function 的靈活又兼具 property 的方便
- 當使用 object 時,getter property 與
Object.defineProperty()
等效;但當使用 class 時,兩者則不太一樣,getter property 會建立在 prototype 上,而Object.defineProperty()
則直接建立在 object 內 - Getter property 具有 lazy 特性,可在適當場合加以使用