這裡我要說的重載(override),确實就是傳統OO中的重載,而不是我們在JavaScript對象中對其同名屬性或方法的重寫(rewrite)。在此我就不詳細講什麼是OOP中的override了,因為隻要是使用.NET來程式設計的程式員都應該很了解的。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
for ( var key in base )
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
{
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
if ( !this[key] )
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
{
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
this[key] = base[key];
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
if ( typeof(base[key]) != 'function' )
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
{
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
delete base[key];
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
}
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
}
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
}
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
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後調用基類方法非常的相似了
,我們就這麼來調用基類方法可以嗎?當然是不可以的,因為這時的方法都屬于基類對象base,它是無法通路子類中的屬性的。不過幸好JScript提供兩個函數,call和apply,于是我們可以使用這樣兩個方法來重新應用this(子類執行個體)對象。調用語句如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
this.base.MethodName.call(this);
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
this.base.MethodName.apply(this, arguments);
第一個語句用來處理沒有參數的override的情況,第二個用來處理調用子類方法有參數,而其參數還需要原樣傳入基類方法的情況。這樣的override語句雖然算不時上sexy,不過他的好處是對基類方法的編寫沒有任何的要求,而且即使錯誤的使用了this.base.MethodName()還是比較容易debug出錯誤來的。
這個override最大問題是什麼呢?就是它隻能支援對子類中,沒有使用同樣override方法的方法進行這種override。好繞口,看看下面這個執行個體就知道問題了:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
<html>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
<head>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
<title>Researh Override in JavaScript OOP</title>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
<meta name="author" content="birdshome@部落格園" />
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
</head>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
<body>
<script language="javascript">
</script>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
</body>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
</html>
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiZpdmLl52bO9CXzJ3b0F2YpRmbJdmbp5WasRXdP9CXzV2Zh1WSvwVbvNmLzd2bsJmbj5yd3d3Lc9CX6MHc0RHaiojIsJye.gif)
三個類grandpa、father和son,它們分别具有兩個屬性和兩個方法。其中的getName方法,是從father中調用了grandpa中被override的同名方法,然後又從son中的getName調用了father中被override的同名方法。這樣就在執行son中的getName時,在father中的getName方法中産生死循環,最後stack
overflow,IE crash
。而其中的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/,如需轉載請自行聯系原部落客。