天天看點

在JavaScript面向對象程式設計中使用重載

這裡我要說的重載(override),确實就是傳統OO中的重載,而不是我們在JavaScript對象中對其同名屬性或方法的重寫(rewrite)。在此我就不詳細講什麼是OOP中的override了,因為隻要是使用.NET來程式設計的程式員都應該很了解的。

在JavaScript面向對象程式設計中使用重載

  for ( var key in base )

在JavaScript面向對象程式設計中使用重載

  {

在JavaScript面向對象程式設計中使用重載

      if ( !this[key] )

在JavaScript面向對象程式設計中使用重載

      {

在JavaScript面向對象程式設計中使用重載

          this[key] = base[key];

在JavaScript面向對象程式設計中使用重載

          if ( typeof(base[key]) != 'function' )

在JavaScript面向對象程式設計中使用重載

          {

在JavaScript面向對象程式設計中使用重載

              delete base[key];

在JavaScript面向對象程式設計中使用重載

          }

在JavaScript面向對象程式設計中使用重載

      }

在JavaScript面向對象程式設計中使用重載

  }

在JavaScript面向對象程式設計中使用重載

  this.base = base;

delete base[key]的作用是删除掉基類對象執行個體中的屬性,因為它們都已經被shallow copy到子類執行個體中了。而this.base

= base;的作用是保留了基類對象執行個體,實際上就是保留了基類中的所有方法,這些保留下來的方法同時也是shallow

copy到子類中了的。隻是我們在子類中可以友善的将其rewrite,注意這裡不是override,而一定是rewrite。rewrite後其實子類執行個體中就沒有了基類中copy過來的同名方法了。

    不過由于我們保留了對基類執行個體的引用this.base = base;,是以即使在子類中被rewrite的方法,基類中仍然可以使用this.base.MethodName()來通路。這個調用基類方法的語句已經和C#中的override後調用基類方法非常的相似了

在JavaScript面向對象程式設計中使用重載

,我們就這麼來調用基類方法可以嗎?當然是不可以的,因為這時的方法都屬于基類對象base,它是無法通路子類中的屬性的。不過幸好JScript提供兩個函數,call和apply,于是我們可以使用這樣兩個方法來重新應用this(子類執行個體)對象。調用語句如下:

在JavaScript面向對象程式設計中使用重載

  this.base.MethodName.call(this);

在JavaScript面向對象程式設計中使用重載

  this.base.MethodName.apply(this, arguments);

    第一個語句用來處理沒有參數的override的情況,第二個用來處理調用子類方法有參數,而其參數還需要原樣傳入基類方法的情況。這樣的override語句雖然算不時上sexy,不過他的好處是對基類方法的編寫沒有任何的要求,而且即使錯誤的使用了this.base.MethodName()還是比較容易debug出錯誤來的。

    這個override最大問題是什麼呢?就是它隻能支援對子類中,沒有使用同樣override方法的方法進行這種override。好繞口,看看下面這個執行個體就知道問題了:

在JavaScript面向對象程式設計中使用重載

<html>

在JavaScript面向對象程式設計中使用重載

<head>

在JavaScript面向對象程式設計中使用重載

    <title>Researh Override in JavaScript OOP</title>

在JavaScript面向對象程式設計中使用重載

    <meta name="author" content="birdshome@部落格園" />

在JavaScript面向對象程式設計中使用重載

    </head>

在JavaScript面向對象程式設計中使用重載

<body>

在JavaScript面向對象程式設計中使用重載

    <script language="javascript">

在JavaScript面向對象程式設計中使用重載

</script>

在JavaScript面向對象程式設計中使用重載
在JavaScript面向對象程式設計中使用重載
在JavaScript面向對象程式設計中使用重載

</body>

在JavaScript面向對象程式設計中使用重載

</html>

在JavaScript面向對象程式設計中使用重載

三個類grandpa、father和son,它們分别具有兩個屬性和兩個方法。其中的getName方法,是從father中調用了grandpa中被override的同名方法,然後又從son中的getName調用了father中被override的同名方法。這樣就在執行son中的getName時,在father中的getName方法中産生死循環,最後stack

overflow,IE crash

在JavaScript面向對象程式設計中使用重載

。而其中的getFamilyName方法,是從son中調用grandpa中被override的同名方法,而grandpa中的getFamilyName沒有再調用任何override方法,是以可以正确的運作。

    由于JavaScript的OOP始終是在做一些模拟的工作,除了能實作某些模拟出來的功能外,同時實作模拟的代碼的複雜度也是應該考慮的,像這樣的override從代碼實作上看非常的輕量級,而且也是很容易了解的。同時可以滿足絕大多數的JS控件的開發,随後我會再給出一個ListView控件的事例,它的實作完全基于'附加繼承法'和我這篇文章中所講到的'重載'技術。

    非常歡迎您的寶貴意見和建議,讓我們開發的更好(copy了dudu的語錄:)。

    Attention:運作代碼alert(s.getName())一定要關閉其它的IE,或避免正在任何IE中填寫表單。

本文轉自部落格園鳥食軒的部落格,原文連結:http://www.cnblogs.com/birdshome/,如需轉載請自行聯系原部落客。

繼續閱讀