現在,Ajax技術發展勢頭迅猛,開發人員已經建立了一個調用大量用戶端javascript、不斷增長的、複雜的系統。因此,在JavaScript上嘗試OO技術便成為了管理複雜性的一種手段。在此過程中,多數開發人員很快便認識到:JavaScript是一種原型化的(prototypical)語言,它缺少OO自身帶來的多種便利。
幾乎每位在開發JavaScript時嘗試應用物件導向技術的開發人員,或多或少都會問自己一個問題:“如何調用父類(super class)的方法?”在Ajax技術還沒有目前這樣炙手可熱之前,這種問題很少出現,因為大多數開發人員僅在進行用戶端form驗證或者簡單的DHTML/DOM操作時使用JavaScript。在那些簡單的解決方案中,函數式編程(functional programming)是很有意義的,物件導向編程則處在次之重要的位置。
現在,Ajax技術發展勢頭迅猛,開發人員已經建立了一個調用大量用戶端JavaScript、不斷增長的、複雜的系統。因此,在JavaScript上嘗試OO技術便成為了管理複雜性的一種手段。在此過程中,多數開發人員很快便認識到:JavaScript是一種原型化的(prototypical)語言,它缺少OO自身帶來的多種便利。
OO設計的主旨和關於它的一些話題談起來很大,但只著眼於Class的定義方式,我認為它是JavaScript開發人員嘗試解決問題的首選。因此,你可以在互連網上找到許多不同的問題解決案例,但在我看過它們後不免有些失望——這些案例都是在某個場合下適用,而不是放之四海而皆準的通法。而我對這個話題的興趣來自於我的team在開發 ThinWire Ajax Framework 的影響。
由於這個架構產生出對用戶端代碼的需求,才使我們“被迫”去實現可靠的、支援父類方法調用的OO模式。通過父類調用,你可以進一步依靠類的繼承特性來核心化通用代碼,從而更易於減少重複代碼,去掉用戶端代碼的壞味道。
下面羅列出了一些在我的研究過程中遇到的解決方式。最終,我沒有從中找出一個可以接收的解決方案,於是我不得不實現一個自己的解決方案,你將在本文的結尾部分看到這個方案。
然而父類調用在這裡是最重要的OO機制,因此我需要一個相應的工作模式,也正是因為在我的觀點中原型化方式是醜陋的,所以我更需要一種更加自然地使用JavaScript定義類的方法。
More Solutions:
好吧,讓我們進入討論。正如開發人員所察覺的那樣,在JS中實現基本的繼承是很容易的事,事實上有一些眾所周知的方法:
醜陋的Solution:
沒有進行父類調用的簡單繼承:
// 提前寫好的JavaScript Class定義和繼承
// 當然,這種代碼很醜陋,散發著代碼的壞味道。
function BaseClass() {
//BaseClass constructor code goes here
}
BaseClass.prototype.getName = function() {
return "BaseClass";
}
function SubClass() {
//SubClass constructor code goes here
}
//Inherit the methods of BaseClass
SubClass.prototype = new BaseClass();
//Override the parent's getName method
SubClass.prototype.getName = function() {
return "SubClass";
}
//Alerts "SubClass"
alert(new SubClass().getName());
導致 IE記憶體泄露 的Solution:
這種實現方式能夠導致在IE中的記憶體流失,你應該盡量避免:
// 運行時的JavaScript Class 定義和繼承
// 看上去很傳統,但這些指令碼會導致在Internet Explorer中的記憶體流失.
function BaseClass() {
this.getName = function() {
return "BaseClass";
};
//BaseClass constructor code goes here
}
function SubClass() {
//在對象執行個體建立時重載父類的getName方法
this.getName = function() {
return "SubClass";
}
//SubClass constructor code goes here
}
//Inherit the methods of BaseClass
SubClass.prototype = new BaseClass();
//Alerts "SubClass"
alert(new SubClass().getName());
就像我在第一個實現方法中所注釋的那樣,第一個實現方法有些醜陋,但它相比引起記憶體流失的第二種方式便是首選了。
我把這兩種方法放在這裡的目的是指出你不應該使用它們。