???
面向對象的
JavaScript
編程
??? Javascript
對于做過
Web
程序的人不應該是陌生,初期是用來做一些簡單的
FORM
驗證,基本上是在玩弄一些技巧性的東西。
IE 4.0
引入了
DHTML
,同時為了對抗
Netscape
的
Javascript,
提出了自己的腳本語言
JScript
,除了遵循
EMAC
的標準之外,同時增加了許多擴展,如下要提到的
OOP
編程就是其中的一個,為了命且概念,我以下提到的
Javascript
都是
Microsoft Internet Explorer 4.0
以上實現的
JScript,
對于
Netscape
,我沒有做過太多的程序,所以一些的區別也就看出來。
??? Javascript
不是一個支持面向對象的語言,更加算不上一個開發平臺,但是
Javascript
提供了一個非常強大的基于
prototype
的面向對象調用功能,你可以在你自己需要的地方使用他們。因此
,
如何使用對象?本文盡可能從
Javascript
面向對象實現原理出發,解析清楚它的工作模型。在了解這些模型之后,你可以在自己的腳本庫中編寫一些實現代碼,然后在其他地方調用。
?
??? Javascript
的語法和
C++
很接近,不過在類實現中沒有使用關鍵字
Class,
實現繼承的時候也沒有采用傳統的
Public
或者
Implement
等等所謂的關鍵字來標示類的實現。這樣的情況下,可能有就有人會問,如何編寫
Javascript
的
Class
,如何實現繼承。我開始也是百思不得其解,后來看了
MSDN,
才知道采用了
prototype
來實現,包括繼承和重載,也可以通過這個關鍵字來實現。
?
??? Javascript
的函數很奇怪,每個都是默認實現了
Optional
的,即參數都可以可選的,
function a(var1,var2,var3),
在調用的過程中
a(),a(value1),a(value1,value2)
等等的調用都是正確的,至少在即使編譯部分可以完整通過,至于其它,只是和函數的實現邏輯比較相關了。
???
以下就
JS
對于類的實現、繼承、重載詳細介紹其實現方式。
??? 1
。實現
??? Js
類的實現就通過函數直接實現的,每個函數可以直接看成
class
,如下代碼
??? function ClassTest1(){
??????? ...//implement code
??? }
??? var a=new ClassTest1
???
??? function ClassTest2(var1){
??? ??? ...//implement code
??? }
??? var b=new ClassTest("value")
???
對于類的屬性,可以通過兩種方式實現
??? 1
)
this."<Property or Method"
的方式實現,在類聲明函數中直接給出函數的實現,如
this.Add=new function(strUserName,strPassword)
這樣的方式調用,編寫的方式在
Class Function
中調用。
??? 2
)通過
ClassFunction.prototype.[FunctionName]=function(var1,var2...){//todo}
這樣的方式完成調用。
???
這兩種方式從目標來看是一致的,按照我個人的觀點來看,區別的只是在于實現方式,通過
this.propertyName
的方式來創建,
Jscript
自動創建了
property
或者
method
的入口,不過從程序的角度而言,還是使用
prototype
的關鍵字實現比較靈活。
???
???
另外
Javascript
也可以和我們
C++
中那種嵌套聲明的方法來聲明
,C++
實現的方法如下
??? Public Class ClassName:ParentClass{
??? ??? Public DataType?FunctionName(){
?
??? ??? }
??? ??? Public Class?ClassName{
??????????? Public DataType?FunctionName(){
??? ??? ??? }
??? ??? }
??? }
???
在
Javascript
當中,當然不存在
class
這樣的關鍵字了
,
所以實現起來有點戲劇性,不過仍然為一個非常巧妙的實現。
??? function className(){
??? ??? //Property Implement
??? ??? this.UserName="blue";
??? ??? //Method Implement
??? ??? this.Add=new function(){
?
??? ??? }
??????? //Sub Class Implement
??? ??? function SubClassName(){
??? ??? ??? this.PropertyName="hi"???????????
??????? }
??? ??? //sub class method implement
??????? SubClassName.prototype.Change=function{
?
??? ??? }
??? }
??? //Main Class Method Implement
????className.prototype.Delete=function(){
?
??? }
???
如上的代碼大致演示了
Javascript
類中屬性和方法的實現,另外有一點比較困惑,整個
class
中都是
public
的,沒有關鍵字
private
之類的可以控制某些方法是否隱藏,那么在我們編寫代碼實現的規范中,我看國外一些程序員都是使用
_functionName
這樣子為函數命的方法來區分,但是在調用過程中實際還可以調用的。
???
實現了屬性和方法,剩下的就是
Event
的實現了,我查找了許多資料,包括整個
MSDN
關于
JScript
的參考,都沒有看到一個很好的模型關于事件實現的,后來參考了一些站點編寫
HTA(HTML Component,
有空我會寫一些相關的文章)的實現,借助于比較扭曲(我個人認為)的方法可以大致的實現基于事件驅動的功能。大致的思路是這樣子的:
??? 1
)
.
將所有的事件定義成屬性,只要簡單的聲明就可以
??? 2
)
.
在需要觸發事件的代碼中判斷事件屬性是否是一個函數,如果是函數,直接執行函數代碼,如果是字符串,那么執行字符串函數,通過
eval(str)
來執行。
??? 3) .
在類的實例當中注冊事件函數。
???
為了簡單說明如上的思路,采用
timer
這樣簡單的例子來表述如上的所提到的內容,如果只是為了簡單的實現
timer
的功能,
Javascript
中
setInterval
函數就可以滿足全部的要求,如下的代碼只是用來說明
Timer
的工作原理。
//Class For Timer
function Timer(iInterval){
?//if not set the timer interval ,then defalut set to 500ms
?this.Interval=iInterval || 500;
?this._handleInterval;
?this.TimerEvent=null
?function Start(){
??if(this.Interval!=0){
???this._handleInterval=setInterval("TimerCallBack()",this.Interval);
??}
?}
?function Start(){
??clearInterval(this._handleInterval);
?}
?function TimerCallBack(){
??if (typeof this.TimerEvent=="function"){
???this.TimerEvent();
??}
??else if(this.TimerEvent!=null && this.TimerEvent.length>0){
???eval(this.TimerEvent);
??}
?}
}?
//Code for Instance
var t=new Timer(3);
//------------------------------------//
//1.
t.TimerEvent=function(){
//todo
}
//2.
t.TimerEvent="alert(\"hello\")";
//3.
t.TimerEvent=tTimerCall;
//----------------------------------//
t.Start();
t.Stop();
function tTimerCall(){
?
}
?
???
實際工作代碼是在
TimerCallBack()
上面實現,事件觸發作為屬性的方式來實現,在應用實例中,代碼提供了三種方法去調用事件,不過在事件的回調當中,我還沒有想到如何可以帶參數,只有才各自的實現當中訪問各自需要的屬性才能夠實現全部的要求。
?
??? 2
。繼承。
???
剛采用了大篇幅的文字去介紹如何實現
Javascript
的各種實現,也就是從邏輯上完成了一個封裝
class
的實現,從某種意義上來說,
class
的實現是真正腳本編程中使用最多的部分,不過如果只是要完成如上的功能,使用
VBScript
來編寫更能更加清晰,畢竟
VBscript
提供了
class
關鍵字,同時提供了
public
和
private
這兩個關鍵字,可以清晰的將公共和私有對象分離,至于事件的實現,也可以采用類似
Javascript
實現的思路,只是對于函數的引用需要采用
GetRef
這個函數,具體的用法可以參考
scripting reference,MSDN
里頭也有詳細的介紹,而
Javascript
強大至于在于如下要說的了,雖然具體的東西可能不多。
???
如上所言,我們已經完成了一個基本的類實現
Timer
,現在要做的是重新編寫這個類,我們簡單的只是想在這個類之中加入一個方法,提供當前的系統時間,方法的名稱為
getSystemDate,
顯然如果全部重新編寫,那就失去了我這里說的意義了。先看看如下的實現。
??? function NewTimer(iInterval){
??? ??? //call super
??? ??? this.base=Timer;
??? ??? this.base
(
iInterval);???????
??? }
??? NewTimer.prototype=new Timer;
??? NewTimer.prototype.getSystemDate=function(){
??? ??? var dt=new Date();
??? ??? return dt.getYear()+"-"+dt.getMonth()+"-"+dt.getDay()
;
??? }
???
???
上述代碼實現了
NewTimer
類,從
Timer
繼承,
Javascript
沒有使用
“
:
”
或者
java
的
public
那樣類似的關鍵字,只是通過
newclassname.prototype=new baseclass
這樣的方法來完成,同時
NewTimer
實現了
getSystemDate
的方法,在
NewTimer
的初始化函數中,我使用了
this.base=Timer
,是為了引用父類的實現,不過在對于父類其他實現函數的調用,到現在我沒有找到一個確定的方法,是否通過
this.base.start()
那樣來調用還是其他的,如果有誰比較清楚的,麻煩告訴我,另外在
netscape
的站點上,我查到有一個特殊的
"__proto__"
的屬性好像是對于父類的直接引用,不過具體的我也沒有嘗試過,在
msdn
中也沒有看到對于
__proto__
的支持。
???
??? 3
。重載
???
或許這個是
OOP
編程中比較復雜的地方了,在
Javascript
的實現中有點無奈,也就是通過
prototype
的方式來完成的,不過因為我不清楚如何調用父類的實現函數,那么在重載中只能夠重新編寫所有的實現了,另外就是在實現中實例化一個父類,然后通過調用它來返回需要的東西。
??? Javascript
中所有的對象都是從
Object
繼承下來的,
object
提供了
toString()
的方法,也就是說如果調用
alert(objInstance)
這樣的過程,實際上是調用了
alert(objInstance.toString())
的方法,如果沒有編寫實現,
object
默認的
toString()
都是
"object object"
這樣子的,在許多地方需要重載這個函數的,比如
Timer,
如果我們希望
var ins=new Timer(5);alert(ins)
調用得到的是
interval
的值
5
,那么就需要重新編寫
toString()
方法了
??? Timer.prototype.toString=function(){ return this.Interval};
???
以上代碼實現之后
alert(ins)
得到的就是
5
了。
?
?
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1926