HTML DOM 的 JavaScript 類別實作方法

基本上,在 JavaScript 裡應該是沒有所謂的類別(class)的。以 Heresy 來看,這樣要把 JavaScript 寫的模組化的話,似乎有點麻煩…不過,所幸在 JavaScript,所有的 function 都可以當作物件來使用,而也此,實際上 JavaScript 還是可以透過它強大的 function 的功能,做到類似 class 的物件導向的寫法的!

寫法呢?大致上就是:

function ClassA( var1 ){  this.memberData1 = var1; // 當作 ClassA 的 member data

// 當作 ClassA 的 member function
this.memberFunction1 = function( var2 ){ alert( this.memberData1 var2 ); };}

在這樣寫後,基本上就可以把 ClassA 當作一個 class 來用了∼可以直接寫:

var obj1 = new ClassA( 0 );obj1.memberFunction1( 10 );

這樣,就會出現顯示「10」的對話框了∼而就算同時有兩個由 ClassA 產生的物件,彼此也不會互相影響到。這樣的寫法,算是相當方便的!

而在把 JavaScript 的程式物件化後,接下來呢?Heresy 想做的,就是繼續把 HTML DOM 的程式,也物件化了∼也就是,把一個複雜的 HTML 介面,從產生到按下去後會觸發的動作,都把它給物件化,以增加重複使用率!

Heresy 的寫法滿簡單的,大致上,就是寫成:

function UI_01(){  // 產生介面的 function
this.createUI = function( widgetID ){ // 取得 root element,作為產生 element 的根元件
var wRoot = document.getElementById( widgetID );
wRoot.style.backgroundColor = "#EEEEEE";
// 產生輸入區
var wInput = document.createElement( "input" );
wRoot.appendChild( wInput );
// 產生按鈕
var wButton = document.createElement( "input" );
wButton.type = "button";
wButton.value = "顯示";
wRoot.appendChild( wButton );
// 產生顯示區
var wDiv = document.createElement( "div" );
wDiv.innerHTML = "尚未輸入";
wRoot.appendChild( wDiv );
// 設定按鈕按下的動作
wButton.onclick = function(){
wDiv.innerHTML = "您輸入的是:" wInput.value;
}; };

// 暫時沒用到的變數
this.pValue = null;
}

如此一來,在網頁裡面,先定義一個 id 是 Test 的 element(例如 <DIV ID="Test"></DIV>)後,再透過 JavaScript 程式:

var mUI = new UI_01();mUI.createUI( "Test" );

就可以快速的產生一個輸入框、一個按鈕和一個用來顯示的 <DIV> 區域了∼而只要按下按鈕後,顯示區域的所顯示的內容,就會從「尚未輸入」變成「您輸入的是: xxxxx」了!

當然,在這個簡單的例子裡,可能看不出來這樣有什麼好處;但是如果是複雜一點、而且有需要重複使用的元件,這樣寫應該是在某種程度上,可以增加可重新使用的效率的∼

不過,當 Heresy 這樣照直覺寫的時候,接下來碰到的問題,則是 HTML DOM 的 element 裡的 callback function 的 scope 問題;要注意的,是在指定 HTML DOM Element 的 callback function 的時候。假設上面的例子,我們希望把它改成在按下按鈕時,把 UI_01pValue 的值變成 wInput 裡的值的話,Heresy 自己很直覺得寫法,會變成是:

wButton.onclick = function(){
this.pValue = wInput.value;
};

但是實際上,這樣的寫法是不對的!因為實際上,在 wButton.onclick = function(){ … } 裡的 scope 和 this.createUI = function( widgetID ){ … } 的 scope 已經不一樣了!

this.createUI = function( widgetID ){ … } 裡,this 指的是 UI_01;而在 wButton.onclick = function(){ … } 裡,this 指的是則是 wButton。也因此,上面的寫法會變成是修改到 wButton.pValue 的值,而不是真正想要修改沒有 UI_01.pValue

遇到這樣的問題該怎麼解的?其實也很簡單,只要先用一個變數來記住 UI_01this 就好了∼寫法可以寫成:

var rThis = this;
wButton.onclick = function(){
rThis.pValue = wInput.value;
};

實際上,同樣的問題也會發生在呼叫函式上∼但是也都可以用同樣的方法解決的。

至此,就算是 Heresy 最近在寫物件導向 JavaScript 的一點心得吧∼ ^^"
這些技巧,基本上應該常常在寫的人,都會注意吧?寫下來,算是給 Heresy 自己做個筆記了。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *