前天講到 descriptor
中 enumerable
、configurable
、writable
、value
,昨天講到 get()
、set()
兩個方法,既然都介紹完了,就進一步的分享今天才知道的知識。XD
在昨天講完後,不知道有沒有人心中的小惡魔被激發地想:既然 value
是這個屬性的值,但是 get()
和 set()
也會被這麼認定,那麼兩個同時存在時會發生什麼事?
先參考昨天的範例去寫一個 descriptor 純粹只有 get()
、set()
的程式:
'use strict'
function Recorder() {
let data = null
let dataHistory = []
Object.defineProperty(this, 'someData', {
get: function() {
return data
},
set: function(value) {
data = value
dataHistory.push(value)
}
})
this.getDataChangeHistory = function() {
return dataHistory
}
}
let recorder = new Recorder()
recorder.someData = 1
recorder.someData = 1
recorder.someData = 2
recorder.someData = 3
recorder.someData = 5
console.log(recorder.getDataChangeHistory())
那假設我把 descriptor 改成這樣呢?
Object.defineProperty(this, 'someData', {
value: 0,
get: function() {
return data
},
set: function(value) {
data = value
dataHistory.push(value)
}
})
這時候就會跳出以下的錯誤訊息:
TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>
系統說這是一個錯誤的 property descriptor,原因在於 accessors 不能和 value
或 writable
特性並存。
所以我們會把 descriptor 分為兩種,一個是利用 get()
、set()
讓存取可以有較多變化的 accessor descriptors,另一個是透過 value
或 writable
單純操作資料的 data descriptors,這兩者是不能並存的。但兩者都可以和 enumerable
、configurable
做搭配。
另外補充一點前天沒提到的,若 configurable
為 false
時,該屬性就無法被 delete
刪除,若嘗試這麼做,一樣會跳出 TypeError。
'use strict'
let obj = {}
// configurable: false
// writable: true
Object.defineProperty(obj, 'key', {
value: 'value',
configurable: false,
writable: true ,
enumerable: true
})
console.log(obj)
// Available
obj['key'] = 'value2'
console.log(obj)
// Unavailable
delete obj.key
console.log(obj)
// Output:
// { key: 'value' }
// { key: 'value2' }
// TypeError: Cannot delete property 'key' of #<Object></Object>
今天先研究到這邊。預計明後兩天分別研究一下用這個方法綁定資料的情境與實作,以及其他相關方法後,就可以找其他看不懂的程式碼來研究啦。