JavaScript: setTimeout (setInterval) 不工作
JavaScript: setTimeout (setInterval) not working
好的,基本上我是在创建一个间隔 class 来处理重复操作。
我有这样的东西:
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);
都不起作用。
超时处理程序中的 this
不是 Interval
对象,它指的是 window 对象(非严格模式)所以 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
}
您 运行 遇到代码上下文问题。当 setTimeout 函数执行您的回调时, "this" 的定义不再是您的 Interval 对象。您需要修改代码,以便维护对 Interval 对象的正确引用。
this.wait = function(time) {
var interval = this;
interval.pause();
setTimeout(function() {
interval.start();
}, time);
}
编辑
我刚刚看到另一个使用 .bind 的答案,从可读性的角度来看,这是一个更简洁的解决方案。关于 .bind 的一个重要注意事项是,它在幕后基本上生成另一个函数来使用 .call 或 [=19= .apply 方法来设置 this
的正确值
在大多数情况下,使用 .bind 获得的可读性是值得的。但是,如果这将成为更大系统的核心组件,那么最好从中榨取每一盎司的性能。在这种特定情况下,这将是避免 .bind 的论据。
基于其他答案的工作示例。
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);
好的,基本上我是在创建一个间隔 class 来处理重复操作。 我有这样的东西:
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);
都不起作用。
this
不是 Interval
对象,它指的是 window 对象(非严格模式)所以 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
}
您 运行 遇到代码上下文问题。当 setTimeout 函数执行您的回调时, "this" 的定义不再是您的 Interval 对象。您需要修改代码,以便维护对 Interval 对象的正确引用。
this.wait = function(time) {
var interval = this;
interval.pause();
setTimeout(function() {
interval.start();
}, time);
}
编辑
我刚刚看到另一个使用 .bind 的答案,从可读性的角度来看,这是一个更简洁的解决方案。关于 .bind 的一个重要注意事项是,它在幕后基本上生成另一个函数来使用 .call 或 [=19= .apply 方法来设置 this
的正确值在大多数情况下,使用 .bind 获得的可读性是值得的。但是,如果这将成为更大系统的核心组件,那么最好从中榨取每一盎司的性能。在这种特定情况下,这将是避免 .bind 的论据。
基于其他答案的工作示例。
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);