JavaScript:setTimeout(setInterval)不起作用

时间:2015-03-18 04:53:47

标签: javascript settimeout setinterval nested

好的,基本上我创建了一个Interval类来处理重复操作。 我有这样的事情:



function Interval(fn, speed) {
	this.fn = fn;
	this.speed = speed;
	this.nt = setInterval(fn, speed);
}




然后我有3种方法:



	this.pause = function() {
		clearInterval(this.nt);
	}

	this.start = function() {
		this.nt = setInterval(this.fn, this.speed);
		return this.nt;
	}

	this.wait = function(time) {
		this.pause();
		setTimeout(function() {
			this.start();
		}, time);
	}




问题出现在第三种方法中。 this.pause();this.start();按预期工作。但是当我将this.start嵌套到setTimeout函数中时,它就会停止工作。我不明白为什么。这是一个例子:



var i = 0:
var nt = new Interval(function() {
    alert('Itineration: '+ i );
    if(i>5);
    nt.pause();
    setTimeout(nt.start, 2000);
    // nt.wait(2000);
  }, 500);




nt.wait(2000);nt.pause(); setTimeout(nt.start, 2000);都无效。

3 个答案:

答案 0 :(得分:4)

超时处理程序中的

this不是Interval对象,它指的是窗口对象(非严格模式),因此this.start()将无法正常工作

一种解决方案是使用Function.bind()

传递自定义上下文
this.wait = function (time) {
    this.pause();
    setTimeout(function () {
        this.start();
    }.bind(this), time);
    // setTimeout(this.start.bind(this), time) as @elclanrs suggested
}

答案 1 :(得分:0)

您遇到代码的上下文问题。当setTimeout函数执行你的回调时,“this”的定义不再是你的Interval对象。您需要修改代码,以便维护对Interval对象的正确引用。

this.wait = function(time) {
    var interval = this;
    interval.pause();
    setTimeout(function() {
        interval.start();
    }, time);
}

修改

我刚刚使用 .bind 看到了另一个答案,从可读性的角度来看,这是一个更清晰的解决方案。关于 .bind 的一个重要注意事项是幕后它基本上会生成另一个函数来使用 .call .apply 方法调用原始函数设置

的正确值

在大多数情况下,使用 .bind 获得的可读性是值得的。但是,如果这将成为更大系统的核心组件,那么最好从其中挤出每一盎司的性能。在这种特定情况下,这将成为避免 .bind 的论据。

答案 2 :(得分:0)

基于其他答案的工作示例。

function Interval(fn, speed) {
    this.fn = fn;
    this.speed = speed;
    this.nt = setInterval(fn, speed);

    this.pause = function () {
        clearInterval(this.nt);
    }

    this.start = function () {
        this.nt = setInterval(this.fn, this.speed);
        return this.nt;
    }

    this.wait = function (time) {
        this.pause();
        setTimeout(function () {
            this.start();
        }.bind(this), time);
    }
}

var i = 0;
var nt = new Interval(function () {
    document.write('<pre>Itineration: ' + i + '</pre>');
    i++;
    nt.wait(2000);  
}, 500);