2010-04-19 38 views
3

我想建立一個函數,如果它在半秒前被調用的時候返回false。Javascript功能:自上次嘗試以來已過半秒鐘?

timething.timechill=function(){ 
    var last 
    if (last){ 
      if ((now.getTime()-last)>500){ 
        return true 
      } 
      else{ 

        return true 
      } 
    } 
    else { 
      last=now.getTime() 
      return false 
    }} 

任何想法?我想避免setTimeout()並忽略輸入,如果它太快以避免溢出。這是一個很好的做法嗎?

+3

如果這是你的代碼複製粘貼,我會建議你不要忘記把';'在您的真實代碼 – fmsf 2010-04-19 11:29:08

+0

感謝所有偉大的答案!當我將頭圍繞在他們身上時,我會成爲一名更好的js程序員。我第一次使用這個網站的方式。 – heorling 2010-04-19 15:14:44

回答

5
timething.timechill = (function() { 
    var lastCall = 0; 
    return function() { 
     if (new Date() - lastCall < 500) 
      return false; 
     lastCall = new Date(); 
     //do stuff 
    } 
})(); 

的這裏的想法是,將(function() { ... })();創建一個匿名函數並立即運行。 timething.timechill未分配此功能。取而代之的是,通過該功能爲內部函數返回

請注意,lastCall未在該內部函數中聲明(使用var關鍵字)。當外部函數返回時,lastCall不會消失,因爲內部函數由於它引用變量而「封閉」了它。

當您稍後運行timething.timechill並遇到此變量時,它將在該函數的變量範圍外搜索該變量並查找之前聲明的變量。當它返回時,該變量仍然不會消失,因爲它是在函數範圍外聲明的。

很難清楚地解釋這個概念,但它非常有用,因爲lastCall對於不需要看到它的其他代碼是不可見的。

+1

謝謝!我最終使用你的代碼進行了一些小修改。我插入了這個else語句: else {lastCall = new Date();返回true; } – heorling 2010-04-19 16:48:34

+0

問題是,Date()調用稍後會導致問題嗎?它只能在特殊情況下調用。 kgiannakakis是正確的嗎? setTimeout是解決這個問題的方法嗎? – heorling 2010-04-19 17:40:33

+0

'setTimeout'通常比輪詢更好。但是如果你已經投票了,我不認爲這會造成額外的問題。它可以在if語句之前用'var current = new Date();'略微優化,然後使用相同的'current'進行比較和賦值,而不是創建兩個'Date'對象。 Firefox有一個靜態的'Date.now()'方法,可能不會創建一個完整的對象,但是你需要爲大多數瀏覽器提供一個解決方法。請參閱https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Date/now – 2010-04-19 20:52:49

0

您定義的函數將始終返回false,因爲last變量永遠不會保存在任何位置。你可以把它作爲一個對象的屬性,或者你可以把它放在一個閉包中。

這裏有一個閉合例子:

timething.timechill = (function() { 
    var last = 0; 

    function timechill() { 
     var now; 

     now = new Date().getTime(); 
     if (last) { 
      if (now - last > 500) { 
       // It's been long enough, allow it and reset 
       last = now; 
       return true; 
      } 
      // Not long enough 
      return false; 
     } 

     // First call 
     last = now; 
     return false; 
    } 

    return timechill; 
})()); 

使用匿名作用域功能來構建timechill功能封閉在last變量。匿名範圍函數返回對timechill函數的引用,該函數被分配到timething.timechill。除了timechill功能以外,其他功能都可以訪問last,它完全是私人的。

(我敢肯定,函數的實際邏輯可重構一點,但我認爲這是非常接近原始的,除了有你回來true,我想你想false一個地方。)

這是否是一個好主意完全取決於你的用例。我不會忙於循環上述。 :-)但是如果你用它來彈出類似SO的東西「你只能每五秒評一次評論」的話,那就沒問題了,儘管在這種情況下我可能會推論它。

+0

感謝您的回答。我試圖避免「堆疊」多個鼠標滾輪事件,讓他們「滾動」我已經嘗試了所有的解決方案,但他們都打破我的代碼,原因是我撓頭。 最後你有「})());」我正在努力理解。 Eclipse告訴我「無效的任務左側」,我試圖修復它沒有工作..但 – heorling 2010-04-19 16:16:44

1

我不認爲這是一個好主意。根據您如何調用此方法,可能會導致「無限循環」行爲。通過setTimeout,您可以進行異步操作 - 在等待時間通過的同時,您不會阻止瀏覽器。大多數瀏覽器會檢測到阻止代碼並禁用腳本。

+0

這並不好,如果我正確理解setTimeout,它只是等待執行腳本嗎?如果它太快,我需要「取消」它,而不是延遲它..我錯過了什麼? – heorling 2010-04-19 15:48:27

0

「last」變量必須存儲在另一個對象中,例如全局變量的窗口對象或此處的時間對象。我從來沒有聽說過「現在」的對象!?

timething.timechill = function(){ 

    if (!timething._last_timechill){ 

     if ((new Date())-timething._last_timechill >= 500) return true; 
     else return false; 

    } else { 

     timething._last_timechill = new Date(); 
     return false; 

    } 

} 

如果您喜歡,您可以用函數中的「窗口」替換「時間」。

編輯:正如其他人指出的,你可以alsostore你的_last_timechill變量封閉。

相關問題