2009年2月23日 星期一

小型計數器

今天用 JavaScript 在實作計數器(Timer.js)時碰到了許多問題,
主因來自於兩個:

  1. Internet Explore(IE)與FireFox(FF)的語法不一

  2. javascript並非物件導向


而第二個問題倒是比較困惱著我,好在這些問題也曾經有人遇過得以解救
主要參考的文獻都是馮旭平大大(哈~~請見諒我直呼名諱)的文章。
因為我打算用 Javascript 撰寫類別的概念,但是此語言並非Class-Based,
而是Prototype-Based,因此寫起來跟以往在寫C#與JAVA時格外不同。
當我使用 setInterval 讓圖片能夠每隔一秒顯示時卻遇到了非常大的一個問題,
問題原由請看下列程式說明:

function Timer(){
this.timer = null;
this.ini = function(){
this.timer_digit = 0;
// this.timer = setInterval(this.runTimer, 1000);
}
}
Timer.prototype.runTimer = function(){
this.timer_digit++;
alert(this.timer_digit);
}


<body onload="var b=new Timer();b.ini();">
</body>

相信大家執行這段程式碼以後會發現 alert(this.timer_digit); 會出現 NaN 而不是累加的數字,
後來我找到問題的原因即是因為 this 這個關鍵字在不同地方使用時會有不一樣的意義。

當 function 是被一個 new 出來的物件呼叫時,在呼叫時會把 this 傳給這個 function 使用


如上例即是 this 會傳到 Timer 這個 function 內,因此這個時候使用的 this 是沒有問題的,
但是當b.ini()呼叫以後,執行到 this.timer = setInterval(this.runTimer, 1000) 之後會每隔一秒跑一次runTimer

但是當runTimer被呼叫起來的時候,已經不是由物件本身自己叫用,這個時候 this 將會變成是 Global 物件。

有興趣看 Global 物件到底是什麼可以試著把 alert 那行改為 alert(this),
最後當我把 runTimer 移到Timer 並在 Timer初始化時用一個變數記著這個new出來的物件時即可。詳情如下所示:

function Timer(){
var ref = this;
this.timer = null;
this.timer_digit = 0;
this.ini = function(){
// this.timer = setInterval(this.runTimer, 1000);
}
this.runTimer = function(){
ref.timer_digit++;
if(ref.timer_digit<5)
alert(ref.timer_digit);
}
}

實作內容請點我

沒有留言:

張貼留言