iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 4
0
Modern Web

我或許沒那麼懂 Web系列 第 4

JS Object.defineProperty(): (3) value V.S. getter & setter

前天講到 descriptorenumerableconfigurablewritablevalue ,昨天講到 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 不能和 valuewritable 特性並存。

所以我們會把 descriptor 分為兩種,一個是利用 get()set() 讓存取可以有較多變化的 accessor descriptors,另一個是透過 valuewritable 單純操作資料的 data descriptors,這兩者是不能並存的。但兩者都可以和 enumerableconfigurable 做搭配。

另外補充一點前天沒提到的,若 configurablefalse 時,該屬性就無法被 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>

今天先研究到這邊。預計明後兩天分別研究一下用這個方法綁定資料的情境與實作,以及其他相關方法後,就可以找其他看不懂的程式碼來研究啦。


上一篇
JS Object.defineProperty(): (2) getter & setter
下一篇
JS Object.defineProperty(): (4) 資料繫結
系列文
我或許沒那麼懂 Web31

尚未有邦友留言

立即登入留言