对象方法中的 setInterval 问题

Trouble with setInterval in an object's method

我想不通为什么当我调用对象的reset方法时,timer还是null。下面是我对象的简化版本,然后是构造新对象并运行代码的 jQuery。有关我的具体问题点,请参阅大写评论。谢谢!

    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); 
        }

    });
});

当您在点击函数回调中使用 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]');

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 ... */
}