首页 > 代码库 > 这题我也是醉了,做一次,错一次

这题我也是醉了,做一次,错一次

  今天在群里看到了一道经典的javascript题型,之前也遇到过,可是再次遇到时,还是做错,还是不理解,因此这里来做个笔记吧!

  不说了,直接上代码吧  

  for(var i=1; i<=9; i++) {
    setTimeout(function(){
      console.log( i );
    },1000 ); 
  }

  看到这里,你知道答案吗?

  好了,不卖关子了,答案是10个10,为什么会这样呢?

  其实原理是这样的,这个是因为,我们在for循环中定义的变量i,在for循环结束后还没有走出它的作用域,循环一次  定时器就会加入任务队列,但是定时器并没有执行。也就是说for循环之后,i依然可以访问,值等于最后一次循环后的值,循环了10次,就有了10次定时器。因此会输处10个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。

 

这题我也是醉了,做一次,错一次