2015-02-24 44 views
2

我無法弄清楚爲什麼當我調用對象的重置方法時,定時器仍爲空。我簡化了我的對象的版本,下面是構建一個新對象並運行代碼的jQuery。見我的具體問題點的大寫評論。謝謝!SetInterval在對象的方法中的問題

var countdownTimer = { 
     // Default vars 
     milliseconds: 120000, 
     interval: 1000, 
     timer: false, 

     /* ... stuff ... */ 
     countdown: function() { 
      var root = this; 
      var originalTime = root.milliseconds; 
      /* ... stuff */ 
      // IN MY MIND THIS NEXT LINE SETS THE INSTANCE OF THIS OBJECT'S TIMER PROPERTY TO THE setIterval's ID. BUT DOESN'T SEEM TO BE CORRECT. WHY? 
      root.timer = setInterval(function() { 
       if (root.milliseconds < 1) { 
        clearInterval(root.timer); // THIS LINE SEEMS TO WORK 
        root.countdownComplete(); // callback function 
        return false; 
       } 
       root.milliseconds = root.milliseconds - root.interval; 

       /* .... stuff ... */ 
      }, root.interval); 
     }, 
     start: function (ms) { 
      if (ms) { 
       this.milliseconds = ms; 
      } 
      if(this.timer) { 
       clearInterval(this.timer); // NOT SURE IF THIS WORKS OR NOT 
      } 
      this.countdown(); 
     }, 
     reset: function (ms) { 
      var root = this; 
      if(root.timer) { 
       clearInterval(root.timer); // THIS DOES NOT WORK 
      } else { 
       console.log('timer not exist!!!!'); // ALWAYS END UP HERE. WHY? 
      } 
      /* .... stuff ... */ 
     }, 
     countdownComplete: function() { } 

    }; 

// Setting up click events to create instances of the countdownTimer 
$(function() { 
    var thisPageCountdown = 4000; 

    $('[data-countdown]').on('click', '[data-countdown-start], [data-countdown-reset]', function() { 
     var $this = $(this); 
     var $wrap = $this.closest('[data-countdown]'); 
     // create instance of countdownTimer 
     var myCountdown = Object.create(countdownTimer); 

     if ($this.is('[data-countdown-start]')) { 
      $this.hide(); 
      $('[data-countdown-reset]', $wrap).css('display', 'block'); 
      myCountdown.$wrap = $wrap; 
      myCountdown.start(thisPageCountdown); 
      // myCountdown.countdownComplete = function() { 
      // alert("Updated Callback!"); 
      // }; 
     } 

     if ($this.is('[data-countdown-reset')) { 
      $this.hide(); 
      $('[data-countdown-start]', $wrap).css('display', 'block'); 

      // RESET CALLED HERE BUT DOESN'T WORK RIGHT. SAYS myCountdown.timer IS STILL null. WHY? 
      myCountdown.reset(thisPageCountdown); 
     } 

    }); 
}); 

回答

1

當您使用var myCountdown = Object.create(countdownTimer);的點擊回調函數裏面你就劃定範圍只對回調,一旦回調執行是垃圾收集。您只需要創建countdownTimer的一個實例,它應該在您的單擊事件處理程序之外。

var thisPageCountdown = 4000; 
// create instance of countdownTimer 
var myCountdown = Object.create(countdownTimer); 

$('[data-countdown]').on('click', '[data-countdown-start], [data-countdown-reset]', function() { 
    var $this = $(this); 
    var $wrap = $this.closest('[data-countdown]'); 
+0

這對我來說很有意義,但我怎麼那麼將有屏幕一次獨立作用於兩個定時器:從上面

實例? – Ben 2015-02-24 20:06:48

+0

@Ben - 在使用重置之前是否開始連續多次使用? – 2015-02-24 20:10:25

+0

每次使用countdownTimer.start它應該清除間隔,然後countdownTimer.start調用countdownTimer.countdown,然後創建一個新的setInterval。通過單擊開始按鈕調用開始操作。它不能再次點擊(它是隱藏的),直到用戶點擊一個重置按鈕,調用countdownTimer.reset – Ben 2015-02-24 20:14:15

0

TL; DR您可以通過避免靜態方法使用關鍵字this的解決您的問題。

當您在靜態javascript方法中使用關鍵字this時,它指向來自調用點的最後一個點之前的項目。例如:

foo.bar(); // inside, this will refer to foo 
foo.bar.foobar(); //inside, this will refer to foo.bar 
var a = foo.bar.foobar(); 
a(); //this will refer to either null or window - oops 

爲了防止這種行爲,你應該總是使用靜態方法,而不是依賴於this關鍵字完全合格的名稱引用。

reset: function (ms) { 
    //var root = this; // don't do this 
    if(countdownTimer.timer) { 
    clearInterval(countdownTimer.timer); 
    } else { 
    console.log('timer not exist!!!!'); 
    } 
    /* .... stuff ... */ 
} 
+0

使用此代碼的結果相同。我認爲是因爲在這個例子中,countodwnTimer是myCountdown對象所基於的原始對象,而不是創建的實際對象(myCoundown)。另外我認爲使用'var root = this'被認爲是很好的做法:https://www.safaribooksonline.com/library/view/javascript-the-good/9780596517748/ch04s03.html – Ben 2015-02-24 20:06:11