关于SetTimeout 时间设为0时。
问题来源: http://blog.csdn.net/lsk_jd/article/details/6080772
这是一个关于Settimeout
时间为0时的一些技巧应用,不过看完后觉得有些问题,
里面的例子,如果onmousedown
改为onmouseup
,onkeypress
改为 onkeyup
那文章里说的问题都没有了。不知道这是为啥?onmousedown
的运作方式又是如何的,或者说文章里那个onmousedown
时focus
,select
不执行是因何,说是单线程的问题,但具体是啥。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
依云回答的是正确的。而我在上周因为你这个问题,而编写了一篇文章:
JavaScript下的setTimeout(fn,0)意味着什么?
你所读的那篇文章讲解的核心是正确的,但是原作者使用了错误的方法来给你演示:
onmousedown
。你被作者的
onmousedown
给误解了,因为Event onmouseXXX
系列API本身相对其他的事件来说稍显复杂。其中,作者演示了代码
onmousedown
系的代码,在未使用setTimeout的情况下,input.select()
看似没有执行。但真实的情况是:
input.select()
执行了,然后被按钮点击的焦点给覆盖了。原文作者的初衷是好的,但其演示的代码误导了自己和读者,并以此得到了一段并不正确的理论。
至于详细的分析请参阅上面我给出的我的文章。
是的,浏览器跑网页里的 JS 是单线程,setTimeout 和直接写的执行顺序会不一样。但是,CSDN 和博客园既不是 W3C 也不是 MDN,出点误导苍生的文章很正常。连 YouTube 上都一堆视频以「优化」的名义教人劣化呢1。文章可能没说错任何一句话,但是现象和解释是不对应的。
这是因为执行顺序的关系。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 的「记录事件」功能,大大简化了这类现象的原因调查流程。
(本答案仅供参考,我也是看的博客园的二手资料,把赞都给 @依云 吧)
JavaScript 是单线程执行的,也就是无法同时执行多段代码,当某一段代码正在执行的时候,所有后续的任务都必须等待,形成一个队列,一旦当前任务执行完毕,再从队列中取出下一个任务。这也常被称为 “阻塞式执行”。
假如当前 JavaScript 进程正在执行一段很耗时的代码,此时发生了一次鼠标点击,那么事件处理程序就被阻塞,用户也无法立即看到反馈,事件处理程序会被放入任务队列,直到前面的代码结束以后才会开始执行。
如果代码中设定了一个
setTimeout
,那么浏览器便会在合适的时间,将代码插入任务队列,如果这个时间设为0
,就代表立即插入队列,但不是立即执行,仍然要等待前面代码执行完毕。所以setTimeout
并不能保证执行的时间,是否及时执行取决于 JavaScript 线程是拥挤还是空闲。对于实际代码的分析,看看这篇文章:http://www.cnblogs.com/fullhouse/archive/2012/10/10/2718542.html
简单点说就是
JS
单线程,执行顺序先DOM
(程序上的) 后渲染(即将页面的表现改变)。所以可能代码中已经将某个<div>
里的文本改变了,但真正的渲染还没开始,而是排在程序中的最后面。setTimeout(callback,0)
则将callback
函数放在了队列中比渲染还后面来执行。这是涉及到浏览器引擎的一个 event loop 机制 event loop 是一个回调函数的队列 当你对setTimeout 或者 对DOM 节点进行操作的时候 浏览器引擎会把他交给 wep api, wep api操作完之后 会把你的回调函数放进 event loop 里面 当你的调用栈 (call stack) 为空的时候 event loop 才会把回调函数顶上去调用栈里调用运行