今天在群里看到了一道经典的javascript题型,之前也遇到过,可是再次遇到时,还是做错,还是不理解,因此这里来做个笔记吧!
不说了,直接上代码吧
for(var i=1; i<=9; i++) {
setTimeout(function(){
console.log( i );
},1000 );
}
看到这里,你知道答案吗?
好了,不卖关子了,答案是9个10,为什么会这样呢?
其实原理是这样的,这个是因为,我们在for循环中定义的变量i,在for循环结束后还没有走出它的作用域,循环一次 定时器就会加入任务队列,但是定时器并没有执行。也就是说for循环之后,i依然可以访问,值等于最后一次循环后的值,循环了9次,就有了9次定时器。因此会输处9个10.
既然这样,那我把上面那个for语句,稍微改一下,改成这样呢?
现在你知道答案吗,答案是这样的:1、2、3、4、5、6、7、8、9然后是9个10,解答如上。
可能这里最难理解的是,setTimeout的方式(注册事件):它有两个参数,第一个参数是函数,第二参数是时间值。
调用setTimeout时,把函数参数,放到事件队列中。等主程序运行完,再调用。
我们可以理解为1000之后,再放入事件队列中,如果此时队列为空,那么就直接调用当前函数。如果前面还有其他的事件,那就等待。
因此setTimeout是一个约会从来都不准时的童鞋
现在我再把代码改一下,改成这样的:
现在你又知道答案吗?
答案是:1、2、3、4、5、6、7、8、9、0、1、2,然后是3次3,然后是9次3,其他的不说了,至于为什么是先出现3次3,然后是9次3呢?其实是因为第二个参数即时间值不一样,所以先执行后一个时间戳
注意:调用setTimeout时,把函数参数,放到事件队列中,等主程序运行完,再调用。即便是时间值为0,它也会等主程序执行完再执行,如果主程序队列为空,就会直接调用。
HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。老版本的浏览器都将最短间隔设为10毫秒。而这里设置为0,其实是想表达立即执行的意思,也就是说,等当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。而实际上是最少4ms。