iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

訪問器描述

在訪問器描述中有一組getter/setter,而不會有value跟writable。這兩個方法分別可以使用get/set寫在物件中,或者是描述器裡面。get可以不帶參數只回傳property的值,這個值可以讓set使用在設置方法,透過這個組合保護屬性或方法。

const contestant = {
  contestantId: 1,
  contestantName: "Alice",

  get useId(){
    return `${this.contestantId}`;
  },

  set useId(item){
    this.contestantId = ++item
  }
}
//直接使用
console.log(contestant.useId);//1

//另外給值執行
contestant.useId = 2
console.log(contestant.useId);//3

嘗試幾個直接寫在物件裡的函式會發現:

//有get,沒有set,在印出的時候不會報錯,但是賦值的話就會跑出錯誤訊息。
const contestant = {
  contestantId: 1,
  contestantName: "Alice",

  get useId(){
    return `${this.contestantId}`;
  },
}

contestant.useId = 2//TypeError: Cannot set property useId of #<Object> which has only a getter



//set沒有get提供值的狀況下會undefined
const contestant = {
  contestantId: 1,
  contestantName: "Alice",

  set useId(item){
    this.contestantId = ++item
  }
}
console.log(contestant.useId);//undefined

//get跟set取用的property不一樣,直接跳過set方法,回傳get
const contestant = {
  contestantId: 1,
  contestantName: "Alice",

  get useId(){
    return `${this.contestantName}`;
  },

  set useId(item){
    this.contestantId = ++item
  }
}
console.log(contestant.useId);//Alice

接著在屬性描述器裡面新增get/set設定:

const contestant = {
  contestantId: 1,
  contestantName: "Alice",
}

//把原本在物件內的函式名稱作為新的屬性名稱,並在這個方法上加上get/set
Object.defineProperty(contestant,'useId',{
  get(){
    return this.contestantId
  },

  set(item){
    this.contestantId = ++item
  }
})

contestant.useId = 2
console.log(contestant.useId);//3

剛剛有提到如果property中已經有get/set,那麽不會有value,但如果寫在物件裡,就不會有任何影響:

const contestant = {
  contestantId: 1,
  contestantName: "Alice",
}

Object.defineProperty(contestant,'useId',{
  get(){
    return this.contestantId
  },

  set(item){
    this.contestantId = ++item
  },
  value:30
})
//TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>

const contestant = {
  contestantId: 1,
  contestantName: "Alice",
  get useId(){
    return this.contestantId
  },

  set useId(item){
    this.contestantId = ++item
  },
}

Object.defineProperty(contestant,'useId',{
  value:20,
})

console.log(Object.getOwnPropertyDescriptor(contestant,'useId'));//{ value: 20, writable: false, enumerable: true, configurable: true }

存取get/set在屬性描述中的內容

最後分別來存取物件與屬性中的get/set:
把get/set函式寫在物件:

const contestant = {
  contestantId: 1,
  contestantName: "Alice",
  get useId(){
    return this.contestantId
  },

  set useId(item){
    this.contestantId = ++item
  },
}

console.log(Object.getOwnPropertyDescriptor(contestant,'useId'));

// {
//   get: [Function: get useId],
//   set: [Function: set useId],
//   enumerable: true,
//   configurable: true
// }

把get/set函式寫在屬性描述中:

const contestant = {
  contestantId: 1,
  contestantName: "Alice",
}

Object.defineProperty(contestant,'useId',{
  get(){
    return this.contestantId
  },

  set(item){
    this.contestantId = ++item
  },
})


console.log(Object.getOwnPropertyDescriptor(contestant,'useId'));

// {
//   get: [Function: get],
//   set: [Function: set],
//   enumerable: false,
//   configurable: false
// }

可以發現,在沒有更動屬性的狀況下,寫在物件的get/set方法的enumerableconfigurable會是true,屬性的則都是false

References

JavaScript Getter and Setter

  1. JavaScript大全(第六版)
  2. 你所不知道的 JS|範疇與 Closures,this 與物件原型 (You Don't Know JS: this & Object Prototypes)
  • MDN
  1. get
  2. set
  3. Object.defineProperty()
  4. Object.getOwnPropertyDescriptor()
  • Javascript Info
  1. Property flags and descriptors
  2. Property getters and setters

上一篇
〈Day8〉屬性描述器(上)
下一篇
〈Day10〉class
系列文
廚藝不精也可以,給自己做一份Javascript小火鍋30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言