从一段问题程序窥探js定时器原理

大家先不要看后面的内容,先看下面这段简短的代码,想象i应该弹出的是多少呢?

var t=null;
var i=0;
function a(){
 i++;
 if(i==20){
  return;
 }
 t=setTimeout(a,17);
}
a();
alert(i);

这就是今天我写效果的时候遇到一个问题,当我设定一个定时器做循环的时候,下面的程序不等我的循环结束就开始运行了。

 

上段程序的答案是"1"。

 

那么为什么程序没等循环完毕就着急地开始运行alert(i)了呢,原因就出在setTimeout的原理上。

 

其实setTimeout和setInterval这两个定时器一旦触发,就是和js程序并行执行的,也就是他们并不在一个时间线上。计时器的作用是仅仅是做一个计划,那就是每隔一段时间执行一次目标方法。

 

比如我们做个周计划每周末都出去玩,这其实就是一个定时器,每隔七天出去玩一次。但是周一到周五还是要上班的,也就是说我们不能因为周末出去玩就周一到周五不干事了。

 

js程序也是这样的,计时器的任务我每到那个时间点会完成,但是其它时间我会继续执行下面的代码。如上程序,a函数运行到定时器前一句的时候,i的值是1,然后执行定时器,17毫秒远远大过程序的运行时间,于是js不等了继续执行,于是alert(i),也就是1。

 

为了证明计时器没有偷懒,我们每隔一段时间弹出一次i,如下程序:

var t=null;
var f=null;
var i=0;
function a(){
 i++;
 if(i==20){
  return;
 }
 t=setTimeout(a,17);
}
function b(){
 alert(i);
 f=setTimeout(b,17);
}
a();
b();

可以发现i的确是从0加到了20。

 

以上啰嗦总结成一句话,那就是定时器和js其他程序是并行执行的,互不影响!

 

于是开头的程序正确的写法应该是这样的:

var t=null;
var i=0;
function a(){
 i++;
 if(i==20){
  alert(i);
  return;
 }
 t=setTimeout(a,1);
}
a();

在程序出口的地方做操作,就可以正确地弹出i了(i=20)。

posted on 2012-07-03 14:09  shawn.xie  阅读(1405)  评论(0编辑  收藏  举报

导航

百度流量统计: