Rumah  >  Soal Jawab  >  teks badan

javascript - 关于SetTimeout 时间设为0时。

问题来源: http://blog.csdn.net/lsk_jd/article/details/6080772

这是一个关于Settimeout时间为0时的一些技巧应用,不过看完后觉得有些问题,
里面的例子,如果onmousedown 改为onmouseup,onkeypress 改为 onkeyup那文章里说的问题都没有了。不知道这是为啥?
onmousedown的运作方式又是如何的,或者说文章里那个onmousedownfocus,select不执行是因何,说是单线程的问题,但具体是啥。

PHP中文网PHP中文网2749 hari yang lalu595

membalas semua(5)saya akan balas

  • ringa_lee

    ringa_lee2017-04-10 15:01:42

    依云回答的是正确的。而我在上周因为你这个问题,而编写了一篇文章:
    JavaScript下的setTimeout(fn,0)意味着什么?

    你所读的那篇文章讲解的核心是正确的,但是原作者使用了错误的方法来给你演示:onmousedown
    你被作者的onmousedown给误解了,因为Event onmouseXXX系列API本身相对其他的事件来说稍显复杂。
    其中,作者演示了代码onmousedown系的代码,在未使用setTimeout的情况下,input.select()看似没有执行。
    但真实的情况是:input.select()执行了,然后被按钮点击的焦点给覆盖了。
    原文作者的初衷是好的,但其演示的代码误导了自己和读者,并以此得到了一段并不正确的理论。
    至于详细的分析请参阅上面我给出的我的文章。

    balas
    0
  • 巴扎黑

    巴扎黑2017-04-10 15:01:42

    是的,浏览器跑网页里的 JS 是单线程,setTimeout 和直接写的执行顺序会不一样。但是,CSDN 和博客园既不是 W3C 也不是 MDN,出点误导苍生的文章很正常。连 YouTube 上都一堆视频以「优化」的名义教人劣化呢1。文章可能没说错任何一句话,但是现象和解释是不对应的。

    如果onmousedown 改为onmouseup,onkeypress 改为 onkeyup那文章里说的问题都没有了。不知道这是为啥?

    这是因为执行顺序的关系。setTimeout 也是因为改变了执行顺序所以会有效果。

    那个选不中 input 内的文本的原因是,在 select 事件之后,又发生了 click 事件(在 mouseup 事件之后),click 事件导致了 DOMActivate 事件,这导致焦点被立即移回按钮,input 被 blur。如果你在这个生成的 input 上监听 select 和 blur 事件的话,可以看到你的事件处理函数也会同步被执行的。不是不执行,而是执行的效果被取消了

    当然,实测在火狐 36.0.1 下,再次 focus 这个 input 时里边的文本首先会被选中然后取消。经过测试,我认为这是浏览器渲染的瑕疵,并没有相应的事件发生。

    @justjavac 回答里提到的文章(因为 markdown 不支持 rel="nofollow" 所以我不作链接了)中第二组例子,字符显示会有「延迟」,原因很简单,处理 keypress 事件时 input 的 value 还没有被改变。等到 input 事件发生时就好。你在 input 事件发生时处理的话就没有这种「延迟」。

    如果你们没有博客园的帐号,没法轻松地复制出里边的代码,就学一个像 Vim 这样功能强大的编辑器,自己做实验试试。

    以上操作全部在火狐 36.0.1 Linux 64 版本上实验的。感谢 Firebug 的「记录事件」功能,大大简化了这类现象的原因调查流程。

    balas
    0
  • 迷茫

    迷茫2017-04-10 15:01:42

    (本答案仅供参考,我也是看的博客园的二手资料,把赞都给 @依云 吧)


    JavaScript 是单线程执行的,也就是无法同时执行多段代码,当某一段代码正在执行的时候,所有后续的任务都必须等待,形成一个队列,一旦当前任务执行完毕,再从队列中取出下一个任务。这也常被称为 “阻塞式执行”。

    假如当前 JavaScript 进程正在执行一段很耗时的代码,此时发生了一次鼠标点击,那么事件处理程序就被阻塞,用户也无法立即看到反馈,事件处理程序会被放入任务队列,直到前面的代码结束以后才会开始执行。

    如果代码中设定了一个 setTimeout,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为 0,就代表立即插入队列,但不是立即执行,仍然要等待前面代码执行完毕。所以 setTimeout 并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。

    对于实际代码的分析,看看这篇文章:http://www.cnblogs.com/fullhouse/archive/2012/10/10/2718542.html

    balas
    0
  • 天蓬老师

    天蓬老师2017-04-10 15:01:42

    简单点说就是 JS 单线程,执行顺序先 DOM(程序上的) 后渲染(即将页面的表现改变)。所以可能代码中已经将某个 <p> 里的文本改变了,但真正的渲染还没开始,而是排在程序中的最后面。

    setTimeout(callback,0) 则将 callback 函数放在了队列中比渲染还后面来执行。

    balas
    0
  • PHP中文网

    PHP中文网2017-04-10 15:01:42

    这是涉及到浏览器引擎的一个 event loop 机制 event loop 是一个回调函数的队列 当你对setTimeout 或者 对DOM 节点进行操作的时候 浏览器引擎会把他交给 wep api, wep api操作完之后 会把你的回调函数放进 event loop 里面 当你的调用栈 (call stack) 为空的时候 event loop 才会把回调函数顶上去调用栈里调用运行

    balas
    0
  • Batalbalas