Javascript中setTimeout设置为0的意义?

Posted 天地会珠海分舵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript中setTimeout设置为0的意义?相关的知识,希望对你有一定的参考价值。

知乎网友提问如下

setTimeout设置为0的意义,求解答?


get是getId。
第一个的focus,select不会触发,为什么呢
第二个设置为0可以触发了,为什么

setTimeout设置为0的意义,简单来说就是为了让setTimeout后的代码先于setTimeout的回调函数运行。如果你有vue使用经验的,可以将其类比成vue中的$nextTick方法,该方法就是在下次 DOM 更新循环结束之后执行延迟回调,以便回调中操作DOM的代码能获得最新的DOM。

为什么会这样呢?这个跟javascript的Event Loop有关系,不难,我这里尝试看是否能简单点跟大家说清楚。

先看下面的代码:

function main() 
  console.log('Hi');
  setTimeout(function cb()   
    console.log('there')
  , 0);
  console.log('JSConfEU')

程序在我们的浏览器中运行时:

  • 首先会执行第一行,在Console控制台中输出’Hi’

  • 到了第二行时,浏览器内部的JS引擎如V8,发现调用的是一个异步方法setTimeout,它首先会把setTimeout放到stack调用栈中,但是因为是异步的,所以该调用立刻就返回了。同时,该异步方法是在浏览器的webapis中执行的(浏览器的另外一个线程),因为设置的超时是0,所以也会立即执行完,然后将回调cb放到 task queue中,等待event loop在下个循环中将cb取出来执行

  • 那下一步v8引擎会打印’JSConfEU’还是回调cb中的‘there’呢?答案是,肯定会打印’JSConfEU’!为什么呢?因为Javascript运行时v8运行的其中一个规则就是,只要调用栈stack里面还有没有执行完的代码,就不会从Callback Queue中取任何任务来执行。


  • 前面的文字结合上图应该能更好理解。图片当前的状态就是webapis那边刚执行完setTimeout,浏览器把回调cb放入到task queue(也就是Callback Queue)中。下一步就是要决定继续跑stack里面的方法,还是task queue中的回调。

经过上面分析,我们现在应该知道在main函数中,虽然setTimeout是设置成0,但是,其中的回调是要等main方法所有的代码都执行完才会执行的。

那么现在我们回到题主的例子中:

  • 第一个focus没有起作用,基本可以断定是因为当前代码中的input元素应该还是虚拟DOM中,页面还没有真正渲染出来,所以这时对其设置focus是无效的。

  • 第二个focus所以起作用,原理就是上面说的setTimeout,虽然设置的是0,但是它的回调是要放到Callback Queue中,等到其他代码都执行完,才会进行调用的。而这里的其他代码,就包括了页面的渲染,也就是说真实DOM已经生成了。

我是@天地会珠海分舵,「青葱日历」和「三日清单」 作者。能力一般,水平有限,觉得我说的还有那么点道理的不妨点个赞关注下!

以上是关于Javascript中setTimeout设置为0的意义?的主要内容,如果未能解决你的问题,请参考以下文章

Javascript中setTimeout设置为0的意义?

Javascript setTimeout,闭包

javascript: 暂停 setTimeout();

JavaScript下的setTimeout(fn,0)的作用,涨知识了

js中 setTimeout延时0毫秒的作用

setTimeout 为0的作用