iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0

Table of Contents

  • 屬性描述器
  • 資料描述
    • writable
    • enumerable
    • configurable
  • 訪問器描述
  • 存取get/set在屬性描述中的內容
  • References


在MDN講解function:prototype的內容中,有列了一張描述function:prototype的Property attributes的表格,因此本文會來解釋什麽是屬性描述器。

屬性描述器

屬性描述器(Property descriptors)主要用於確定查看與設定Property的attributes,這些描述器讓我們能查看某個屬性(property)的…屬性(attribute),擁有他所描述的property attribute同名的property,也就是說屬性描述器這個物件中使用property列出attribute,並使用相應的方法來讀取和修改它們。

屬性描述器分為主要兩類:資料描述(data descriptor)跟訪問器描述(accessor descriptor)。資料描述是一個具有值的property,訪問器描述則是主要由getter/setter組成的函式property。

(看書或查資料的時候,有些內容會把property翻成特性,但感覺這樣使用很容易混淆,因此接下來的內容會直接使用propertyattribute來區分差異)

如何看到property的attribute:

const contestant = {
  contestantId: 1
}

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

上面分別印出valuewritableenumerableconfigurable,它們組成資料描述。

資料描述

資料描述除了用來表示property值的value,分別有writableenumerableconfigurable

我們可以使用Object.defineProperty()方法更改這些property,其語法為Object.defineProperty(obj,propertyName, descriptor),要注意的是propertyName需要單引號或雙引號括住。

writable

writable決定property的值能不能被修改。如果設定為true,那麽property值就可以被更改。

在前面介紹屬性描述器時,使用以下的物件來示範屬性描述:

const contestant = {
  contestantId: 1,
}

再使用Object.defineProperty()方法來更改contestantIdproperty的writable:

Object.defineProperty(contestant,'contestantId',{
  writable: false,
})

//嘗試更改,就會發生錯誤
contestant.contestantId = 30//TypeError: Cannot assign to read only property 'contestantId' of object '#<Object>'

enumerable

enumerable決定property是否可被列舉的。在使用前幾天提到for-inObject.keys()這兩個方法的時候,就是判斷property是否為enumerable,決定這個property能不能被這些方法使用。

在下面的範例中,我們將contestantIdproperty的enumerable設置為 false

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

Object.defineProperty(contestant, 'contestantId', {
  enumerable:false,
  // configurable:false,
})

for(const key in contestant){
  console.log(key);//contestantName
}

可以看到在使用for-in時,只有contestantName被迭代,contestantId就像被隱藏起來。

如果只想知道某個property能不能被列舉,可以使用Object.prototype.propertyIsEnumerable() 方法確認,使用這個方法會回傳一個Boolean值,來表示是否能列舉。

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

Object.defineProperty(contestant, 'contestantId', {
  enumerable:false,
})

console.log(contestant.propertyIsEnumerable('contestantId'))//false;

在剛才已經設定contestant.contestantId的enumerable是false,因此Object.prototype.propertyIsEnumerable()回傳一個false回來。

configurable

configurable指的是property的attribute能不能被修改。如果是true,property就可以被刪除,也可以任意修改attribute。一旦把true改成false,就無法再把configurable改回true

configurablefalse的話,也不能更改enumerable,無法把writablefalse改回true

以下示範被configurable影響會發生什麽:

const contestant = {
  contestantId: 1,
}

// 'contestantId'的configurable attribute改為false
Object.defineProperty(contestant, 'contestantId', {
  configurable:false
})

// 嘗試修改'contestantId'的writable的attribute,不會報錯
Object.defineProperty(contestant, 'contestantId', {
  writable:false
})

// 嘗試將 'contestantId'的configurable的attribute設置為true會報錯
Object.defineProperty(contestant, 'contestantId', {
  writable:true,//TypeError: Cannot redefine property: contestantId
})

// 嘗試將 'contestantId' 的enumerable的attribute設置false,將會報錯
Object.defineProperty(contestant, 'contestantId', {
  configurable:true,
  enumerable:false
 //TypeError: Cannot redefine property: contestantId

唯一能被更改的attribute只有在writabletrue的狀況。假設在configurable是false的狀態下把writable改成false,就會像前面說,無法再把writable改回true

回到一開始


讓我們來讀這張表格:Function.prototype的property attributes,是可以寫入、不可列舉、不可配置的,也告訴我們Function.prototypeattributes都無法被修改,最多就只能修改property的值。

(本文接續〈Day9〉屬性描述器(下))


上一篇
〈Day7〉建構函式的原型與new運算子
下一篇
〈Day9〉屬性描述器(下)
系列文
廚藝不精也可以,給自己做一份Javascript小火鍋30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言