setTimeout和setInterval中使用this

JavaScript代碼閉包

  1. var roll = function(objid, step, direct)  

其中objid爲要滾動的容器ID,step爲每一輪滾動的距離,direct爲滾動方向。基礎結構和一些方法就不去管了,直接進入關鍵點。this

roll類的主要方法(都經過prototype設置)有:spa

initroll(); //初始化滾動
playroll(); //開始滾動
stoproll(); //中止滾動
rollPlaying(); //滾動處理
rollReset(); //重置滾動內容prototype

能夠看出,個人設想是,建立滾動版只須要:code

JavaScript代碼
  1. var imgroll = new roll('rollImages', 120, 'TOP');   
  2. imgroll.initroll();  

這裏已經在建立實例的時候初始化了,爲何還要initroll呢?由於我想,滾動動做並非加載後當即執行的,而是在設定的幾秒時間後,因此在initroll()中的最重要的內容即是:ip

JavaScript代碼
  1. roll.prototype.initroll = function(){   
  2.     this.objtimeout = setTimeout(this.playroll, this.iResume);   
  3. }  

有經驗的人可能看出了這裏的問題,但是我卻一點都沒有發覺,這裏記錄一下問題一作用域

playroll(),stoproll()都只是開關來控制rollPlaying(),他們的內容分別是:it

JavaScript代碼
  1. roll.prototype.playroll = function(){   
  2.     this.objrolling = setInterval(this.rollPlaying, this.iTime);   
  3. }  
JavaScript代碼
  1. roll.prototype.stoproll = function(){   
  2.      clearTimeout(this.objtimeout);   
  3.      clearInterval(this.objrolling);   
  4. }  

這裏playroll()出了和上面同樣的問題記錄問題二io

rollPlaying()中的滾動處理自己並無什麼問題,可是由於上面出現的錯誤而致使了運行出錯。那麼問題在哪裏呢?function

問題一:setTimeout(func, time)裏面的func我使用了this關鍵字,來標識是類實例的方法,至少我我的一直認爲是這樣的,func參數中使用this關鍵字自己並無問題, 能夠正確在time時間後執行playroll(),但是在playroll()裏面就碰到了問題二。(可能有人會說,你的setTimeout的func參數沒有帶括號,實事證實有括號的狀況比沒有更慘烈。。。)

問題二:可見我在playroll()中使用了大量的this關鍵字來標識roll類實例的元素或方法,可是由於問題一是在setTimeout中使用playroll()這個方法,所以這裏的this已經不是我設想的類實例的this關鍵字了。我至今尚未弄明白在前面的setTimeout中使用this關鍵字的方法致使了playroll中的this變成了什麼,總而言之這個this已經不是roll的一個實例了。前面也說playroll()中的錯誤和initroll()中的錯誤同樣,一樣致使了rollPlaying()中的this關鍵字失效。

解決問題的方法應該有兩個:其一是不使用this關鍵字而用其餘的方式替代(由於我以爲太麻煩並且會破壞結構因而放棄了);其二是我如今用的解決方案,以下:

JavaScript代碼
  1. roll.prototype.initroll = function(){   
  2.     var o = this;   
  3.     this.objtimeout = setTimeout(function(){o.playroll(o)}, this.iResume);   
  4. }  
JavaScript代碼
  1. roll.prototype.playroll = function(o){   
  2.     this.objrolling = setInterval(function(){o.rollPlaying();}, this.iTime);   
  3. }  

我在initroll()中建立了一個變量o爲this自己,再使用匿名方法把o做爲實例自己,也做爲參數傳遞給了playroll(),爲何要既做爲實例自己又做爲參數呢?做爲實例的做用是能夠在playroll()中使用this關鍵字,而做爲參數是爲了在playroll()當中不用再爲setInterval從新申明一個實例。

有人可能會說,爲何不setTimeout(function(){this.playroll()}, this.iResume)呢?這樣顯然不行的緣由連試都不用試了,由於這樣的狀況下匿名方法內的this關鍵字變成了匿名方法自己而不是外部類,因此才須要一個變量來處理,或者能夠看做一個閉包,在initroll結束以後o變量的做用域仍然存在。

爲了這個問題繞了一些彎路,以爲應該記錄一下,以備後患。

相關文章
相關標籤/搜索