星期五, 6月 07, 2013

[JavaScript] Prototype Chain

  這次延續上次的 prototype,稍微討論一下 prototype chain。這也是 JavaScript很特別的繼承方式下的方法。我參照 Professional JavaScript for Web Developers - Nicholas C. Zakas的 prototype chain的範例實作以及圖片說明如下。

function SuperType(){
  this.property = true;
}

SuperType.prototype.getSuperValue = function (){
  return this.property;
};

function SubType() {
  this.subproperty = false;
}

//inherit from SuperType
SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function () {
  return this.subproperty;
};

var instance = new SubType();
window.console.log(instance.getSuperValue());Check out this Pen!


 
  我們有兩個類別 SuperType以及 SubType,都各自有其屬性跟方法。其差別在於 SubType有新增一個 SuperType的 instance並且指定為他的 prototype(Line 11)。這差異也造成三個地方要注意:

  1. 上圖有了  SubType Prototype 的 __proto__到 SuperType Prototype這個連結關係,而原本在 SuperType存在的屬性跟方法也同時存在 SubType.prototype。

  2.  getSuperValue()這方法仍然在 SuperType.prototype物件當中,那是因為我們宣告他是在 SuperType.prototype當中。而 property則會在 SubType.prototype這個物件當中,是因為他是 instance物件,隨著 new 的物件而存在,我們宣告了 SubType.prototype = new SuperType(),其 SuperType的  this就相當於 SubType.prototype (若要更加延伸探討原因可以參考 [JavaScript] Conditions of this object)。

  3. 同時也注意一點就是 instance.constructor指向 SuperType,原因是 SubType.prototype的 constructor屬性也被複寫過去而重新指向到SuperType了。

  Prototype Chaining 延展了 prototype搜尋方法跟屬性的機制,若在讀取一個 instance的屬性或方法的時候沒有被找到,會往他的 prototype繼續搜尋。在此案例當我們呼叫 instance.getSuperValue()時候會有三個搜尋的步驟: 1) instance ->2) SubType.prototype->3) SuperType.prototype。

  Default Prototypes

  在 JavaScript的 Reference Type都繼承自 Object,所以上述範例實際上會是下圖(參考Professional JavaScript for Web Developers Chapter.6 Object-Oriented Programming)。當我們呼叫 instance.toString(),實際上是呼叫 Object.prototype的 toString()方法。

  延伸閱讀: [JavaScript] Prototype Memo

  Prototype的觀念一直是 JavaScript蠻值得探討的一個話題,文章若有敘述不清楚地方歡迎大家找我討論,也歡迎大家指教補述。

3 則留言:

小莊 - kvzhuang 提到...

基本上
SubType.prototype = new SuperType();的意義,我們可以把他想成 SuperType.call(SubType.prototype);

所以這邊的 SuperType.裡面 this.property這個 this context物件所指的就是 SubType.prototype了.

小莊 - kvzhuang 提到...

根據Kuanling Huang的勘誤並不等於

SubType.prototype = new SuperType();的意義
SuperType.call(SubType.prototype);

http://codepen.io/kvzhuang/pen/ErvfF
此測試可以發現,然而 SuperType.call(SubType.prototype);的確可以改變 context,並將 SuperType的 this.property的值帶給 SubType.

工人 提到...

請問第二張圖中,SuperType Prototype的constructor、__proto__屬性有畫反麼?
這樣看起像 constructor連到 Object Prototype、__proto__連到 SuperType
^^ 謝謝您的教學,剛好在看這個

http://www.benben.cc/blog/?p=320 這個昨晚看到覺得裡面圖很棒的網誌,有興趣可以一起參考。