iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 27
0
Modern Web

【這些年我似是非懂的 Javascript】系列 第 27

【這些年我似是非懂的 Javascript】Day 27 - 物件 # Part 3 # 特性描述器

今天要主要來分享一下特性描述器。

特性描述器 (property descriptor)

在 ES5 之前 JS 無法讓你判定該物件特性的"特徵",
意思是說你沒辦法知道他是不是 read-only 之類的。
至於以前怎麼知道他是不是...
書中沒有特別提道,
感覺只能用猜的或是直接嘗試(我自己猜的)。

但是在 ES5 增加了一個功能叫做特性描述器 (property descriptor)。

const obj = {
    a: 17
};

Object.getOwnPropertyDescriptor(obj,"a");
/*
{
    value: 17,
    writable: true,
    enumerable: true,
    configurable: true
}
*/

由上述的範例可以看到他除了 value 之外,他還有三個特徵。

  • 可寫入的 (Writable)
  • 可列舉的 (Enumerable)
  • 可配置的 (Configurable)

那我們該如何修改這特徵?
可以使用 Object.defineProperty(..) 新增或是修改現有的特性。
要注意的是如果是修改現有的特性的話他要是可配置的(configurable)。

const obj = {}; // 給個空物件

Object.defineProperty(obj,"a",{
    value: 17,
    writable: true,
    enumerable: true,
    configurable: true
});

obj.a; // 17  出現啦~

接著我們針對這三個特徵來一一說明。

可寫入的 (Writable)

這部分很簡單,這邊就是單純你可以決定你能否變更一個特性的值。

const obj = {}; // 給個空物件

Object.defineProperty(obj,"a",{
    value: 17,
    writable: false,
    enumerable: true,
    configurable: true
});

obj.a = 123;
obj.a; // 17  Ops 還是原本的 17

如果你不是在嚴格模式下,你的更改值這動作會直接被吃掉,他也不會跟你說更改失敗,
但是反之你如果在嚴格模式下,他會直接噴爆你給你個 TypeError 並且很貼心的跟你說這是個不可寫入的特性。

可列舉的 (Enumerable)

這個馬上之後會提到這邊先提一點點,這部分主要會影響到的是 for .. in 迴圈 等等之類的。

來個範例

const obj = {
    name: 'robin'
}

Object.defineProperty(obj,"age",{
    value: 16,
    writable: true,
    enumerable: true,
    configurable: true
});

for(let targetProp in obj){
    console.log(targetProp);
};
// name
// age

Object.defineProperty(obj,"age",{
    value: 16,
    writable: true,
    enumerable: false, // 把 age 改成不可列舉
    configurable: true
});


for(let targetProp in obj){
    console.log(targetProp);
};
// name
// 啊... 看不到 age 了

可配置的 (Configurable)

可配置就是剛剛提到的Object.defineProperty(..),能不能修改就是看這個啦。

const obj = {
    a: 17
}

Object.defineProperty(obj,"a",{
    value: 16,
    writable: true,
    enumerable: true,
    configurable: false // 設定不可改
});

Object.defineProperty(obj,"a",{
    value: 18,
    writable: true,
    enumerable: true,
    configurable: true // 設定可改
}); // TypeError 

這邊不管你是不是嚴格模式都會噴你 TypeError,那如果從 false 想把它改回來怎麼辦...?
答案是你沒有回頭路xDD
那如果我直接刪掉它這個特性呢?

const obj = {
    a: 17
}

delete obj.a;
obj.a; // undefined  不見了

Object.defineProperty(obj,"a",{
    value: 16,
    writable: true,
    enumerable: true,
    configurable: false // 設定不可改
});

obj.a; // 16
delete obj.a;
obj.a; // 16  砍不掉啊啊啊啊

以上是今天的內容,
也認識到了特性描述器這神奇的東東。
感謝您的收看我們明天見~


參考來源:

你所不知道的 JS|範疇與 Closures,this 與物件原型 (You Don't Know JS: this & Object Prototypes))


上一篇
【這些年我似是非懂的 Javascript】Day 26 - 物件 # Part 2
下一篇
【這些年我似是非懂的 Javascript】Day 28 - 物件 # Part 4 # 特性描述器 Combo
系列文
【這些年我似是非懂的 Javascript】34

尚未有邦友留言

立即登入留言