iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 24
0
自我挑戰組

學JS的心路歷程系列 第 24

學JS的心路歷程 Day24 - 物件與原型(三)

  • 分享至 

  • xImage
  •  

昨天有說明到函式與建構式的原型,及指定建構式函式原型為另一個建構式函式,但其實這會造成覆寫 constructor 的問題。

覆寫 constructor 的問題

我們昨天有提到「建構式函式可以透過 .constructor 來存取建立物件的函式以此來作類型檢查。」,但是這個例子卻會導致 trickyMan 的建構式的原型被覆寫,無法去判斷。

function Person(){};
Person.prototype.say = "Hi";

function trickyMan(){};
trickyMan.prototype = new Person();

var Jason = new trickyMan();
trickyMan.constructor === trickyMan;//false

所以如果在 Jason 物件上呼叫 .constructor ,會無法找到直到在 Person 上找到參照 Person 函式的 constructor
但是,這事實上是錯誤的,如果我問是哪個函式建立了 Jason 物件,會得到 Person 這可能會產生一些 Bug。

幸好在 JS 中,物件的每個屬性都有一個屬性描述子( property desciptor ),可以夠過它設定以下鍵值:

  • configurable 設定
    • true - 表屬性描述子可被修改及刪除
    • false - 上述兩個動作都將被禁止
  • enumerable 列舉
    • true - 屬性能在物件的 for-in 迴圈操作中出現
  • value
    設定屬性的鍵值
  • writable 寫入
    • true - 表可以透過設值敘述來修改屬性值
  • get
    定義取值( getter )函式,可用來取得屬性值。無法與 value 及 writable 一起設定
  • set
    定義設值( setter )函式,可以用來對屬性指派一個值。無法與 value 及 writable 一起設定

先來個簡單的例子:

Jason.age = 29;

age 這個屬性會是 可設定、可列舉並且可寫入的,它的值被設為 29getset 函式則會是 undefined

如果要對上述設定值做更動的話,可以用 Object.defineProperty

var Jason = {};
Jason.say = "R~";

Object.defineProperty(Jason,"age",{
    configurable : false,
    enumerable : false,
    value : 29,
    writable : true
});
console.log("age" in Jason);

for(let key in Jason){
    console.log(key);
}

好,現在我知道有這東西了,但這跟一開始說的 constructor 有關係嗎?

當然有!我們試著用 trickyMan 擴展( extend )Person 時(也可以說是讓 trickyMan 成為 Person 的子類別),就失去原本保存在 constructor 屬性上的 trickyMan 原型。

我們可以用 Object.defineProperty 在新的 trickyMan.prototype 上定義一個新的 constructor 屬性。

function Person(){};
Person.prototype.say = "Hi";

function trickyMan(){};
trickyMan.prototype = new Person();

Object.defineProperty(trickyMan,"constructor",{
    enumerable : false,
    value : trickyMan,
    writable : true
});

var Jason = new trickyMan();
trickyMan.constructor === trickyMan;//true

那麼,今天就到這邊,一樣如果有錯誤及來源未附上也歡迎留言指正,那麼我們明天見。

參考資料:
忍者 JavaScript 開發技巧探秘
你所不知道的 JS
Javascripter 必須知道的繼承 prototype,[[prototype]],proto
該來理解 JavaScript 的原型鍊了
proto VS. prototype in JavaScript


上一篇
學JS的心路歷程 Day23 -物件與原型(二)
下一篇
學JS的心路歷程 Day25 - JS 的 Class
系列文
學JS的心路歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言