我正在开发一个相当大的应用程序,我需要在一个特定的时间间隔按下一个键时重新调用一个函数。应用程序的部分内容我无法编辑,但它正在替换我的.onkeyup()侦听器,有时间隔只是永远留在那里。我真正想要的是在对象被破坏,重新分配等时间隔停止...在setInterval(),绑定,闭包之后,我做了这个以尝试一些东西,现在我甚至更困惑:
function myInterval(){
this.name = 'Paul'
that=this;
this.go = function go(){
if(that){
this.interval = setTimeout(function(){
console.log(that.name);
that.go();
},100);
};
console.log(that.name);
};
};
periodic = new myInterval();
periodic.go();
setTimeout(function(){
periodic.name='George';
}, 200);
setTimeout(function(){
periodic.name ='John';
periodic.go = '';
periodic.name = 'Ringo'
}, 300);
输出:
Paul
Paul
Paul
George
George
Ringo
> Uncaught TypeError: Property 'go' of object #<myInterval> is not a function
因此,重新分配该功能是有效的,但如果我更换
periodic.go = '';
与
periodic = '';
我得到了
Paul
Paul
Paul
George
George
John
John
...
依此类推;间隔永不停止......
任何人都可以解释一下吗?
是否有一个共同的,优雅的解决方案,以确保我不会将运行间隔减少到以太?
答案 0 :(得分:2)
var timer = setTimeout(func,100)
清除它
if(timer)
clearTimeout(timer)
如果是间隔
var timer = setInterval(func,100)
清除它
if(timer)
clearInterval(timer)
EX
function myInterval(){
this.name = 'Paul'
that=this;
this.go = function go(){
if(that){
this.interval = setTimeout(function(){
console.log(that.name);
that.go();
},100);
};
console.log(that.name);
};
this.stop = function(){ if(this.interval) clearInterval(this.interval);};
};
答案 1 :(得分:1)
间隔永不停止......任何人都可以解释一下吗?
在闭包范围内捕获的变量就是这样的原因,下面的代码将在同一范围内使用变量o将o设置为null。
注意:我更喜欢使用闭包创建者来限制范围并防止其他意外。以下将创建闭包,以保持代码简单。
var o = {};
setTimeout(function(){//closure accessing o directly
console.log("why is o null here:",o);
},100);
o=null;
以下代码将使用o作为传递o,传递o现在被捕获在创建的闭包范围中,将o设置为null不会影响传递的o。变异o(o.something = 22)将影响传递o。 (谷歌“按价值参考javascript”参考)
var o = {};
setTimeout((function(o){
return function(){//closure accessing passed o
console.log("why is o not here:",o);
};
}(o)),100);
o=null;
要解决循环创建closurs中的常见问题,请将变量(i)传递给返回闭包的函数
for(var i = 0;i<10;i++){
setTimeout((function(i){
return function(){//not using i in the for loop but the passed one
console.log("and i is:",i);//0 to 9
};
}(i)),100);
}
因为将i变量放在与闭包相同的范围内会给你带来不必要的结果:
for(var i = 0;i<10;i++){
setTimeout(function(){
console.log("and i is:",i);//10 times and i is: 10
},100);
}
为什么periodic.go =“”的工作与通过引用传递值有关。它的工作原理如下代码所示:
function test(o){
o=22;//no mutation but an assignment
}
var o = {name:"me"};
test(o);
console.log(o);//Object { name="me" }
function test2(o){
o.name="you";//mutates
}
test2(o);
console.log(o);//Object { name="you"}
如何解决
我已经改变了你的代码以利用共享成员的protype(go函数)并创建闭包以确保闭包的范围仅限于你实际需要的内容。
有关详细信息,请阅读introduction to constructor function and the this variable。
function MyInterval(){//capitalize constructor
this.name = 'Paul';
this.doContinue = true;
this.timeoutid = false;
};
MyInterval.prototype.closures ={//creates closures with limited scope
//closure for the go function setting the invoking object
go:function(me){
return function(){
console.log("In go, name is:",me.name);
me.go();
//de reference "me", we no longer need it
// can't do this in a setInterval though
me=null;
};
}
}
MyInterval.prototype.go = function(){
if(this.constructor===MyInterval){
//if you were to call go multiple times
if(this.timeoutid)
clearTimeout(this.timeoutid);
//do it again if this.doContinue is true
this.timeoutid = (this.doContinue)? setTimeout(
this.closures.go(this)
//creates a closure function
,100
):false;
return;
};
console.log("this is not the correct value:",this);
};
//added stop, good call from shadow, now you can stop immediately
// or set doContinue to false and let it run it's course
MyInterval.prototype.stop = function(){
if(this.timeoutid)
clearTimeout(this.timeoutid);
this.timeoutid=false;
};
periodic = new MyInterval();
periodic.go();
//because the clearTimeout you can accedentally do something silly like:
periodic.go();
periodic.go();
setTimeout(function(){
periodic.name='George';
}, 150);
setTimeout(function(){
periodic.name ='John';
periodic.doContinue = false;
periodic.name = 'Ringo'
}, 250);
答案 2 :(得分:1)
在您的代码中:
function myInterval(){
this.name = 'Paul'
that=this;
当你第一次调用 myInterval 并且执行上面的行时,变成了全局,我认为你的意思是保持本地化。否则, 将引用最后创建的实例,这不一定是“当前”实例。
无论如何,执行此操作的最佳方法是为实例提供 stop 方法。所以你这样做:
// By convention, constructors start with a capital letter
function MyInterval() {
// Use a more suitable name than "that" to reference the instance
var interval = this;
this.name = 'Paul'
// This keeps calling itself every 100ms
this.go = function go(){
// Keep a reference to the timeout so it can be cancelled
this.timeout = setTimeout(function(){
console.log('setTimeout: ' + interval.name);
interval.go();
}, 100);
console.log('Go: ' + interval.name);
};
// Stop the timeout
this.stop = function() {
if (interval.timeout) {
clearTimeout(interval.timeout);
}
};
};
var periodic = new MyInterval();
// In 100 ms, it will log its name
periodic.go();
// In 200 ms its name will be changed
setTimeout(function(){
periodic.name='George';
}, 200);
// In 500 ms its name will be changed and it will be cancelled.
setTimeout(function(){
periodic.name ='John';
// call stop here
periodic.stop();
periodic.name = 'Ringo'
}, 500);