JavaScript调用堆栈及setTimeout使用方法深入剖析


Posted in Javascript onFebruary 16, 2013

Javascript中会经常用到setTimeout来推迟一个函数的执行,如:

setTimeout(function(){alert("Hello World");},1000);

会在执行到这句话后延迟1秒钟来弹出alert窗口。那么再看这一段:
function a(){ 
setTimeout(function() {alert(1)}, 0); 
alert(2); 
} 
a();

注意这段代码中的setTimeout延迟设为了0,就是延迟0毫秒,貌似是不做任何延迟立刻执行,即1,2。但实际的执行结果确是2,1。为什么?这得从Javascript调用堆栈(call stack)和setTimeout的功能说起。

首先,JavaScript是单线程的,即同一时间只执行一条代码,所以每一个JavaScript代码执行块会“阻塞”其它异步事件的执行。其次,和其他的编程语言一样,Javascript中的函数调用也是通过堆栈实现的。在执行函数a的时候,a先入栈,如果不给alert(1)加setTimeout,那么alert(1)第2个入栈,最后是alert(2)。但现在给alert(1)加上setTimeout后,alert(1)就被加入到了一个新的堆栈中等待,并“尽可能快”的执行。这个尽可能快就是指在a的堆栈完成后就立刻执行,因此实际的执行结果就是先alert(2),再alert(1)。在这里setTimeout实际上是让alert(1)脱离了当前函数调用堆栈。看下面一个例子:

<input name="input" onkeydown="alert(this.value)" type="text" value="a" />

这样一段函数意图是每输入一个字符就把当前input里的所有字符都alert出来,但实际效果确是alert出按键之前的内容。这里,我们就可以利用setTimeout(0)来实现。
<input onkeydown="var me=this; setTimeout(function(){alert(me.value)}, 0)" name="input" type="text" value="a" />

这样当onkeydown事件触发的时候,alert就被放入了下一个调用堆栈,一旦onkeydown事件触发的堆栈关闭后就开始执行。当然浏览器还有个onkeyup事件也可以实现我们的需求。

这样的setTimeout用法在实际项目中还是会时常遇到。比如浏览器会聪明的等到一个函数堆栈结束后才改变DOM,如果再这个函数堆栈中把页面背景先从白色设为红色,再设回白色,那么浏览器会认为DOM没有发生任何改变而忽略这两句话,因此我们可以通过setTimeout把“设回白色”函数加入下一个堆栈,那么就可以确保背景颜色发生过改变了(虽然速度很快可能无法被察觉)。

总之,setTimeout增加了Javascript函数调用的灵活性,为函数执行顺序的调度提供极大便利。

Javascript 相关文章推荐
javascript 面向对象,实现namespace,class,继承,重载
Oct 29 Javascript
jquery自动切换tabs选项卡的具体实现
Dec 24 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
Dec 27 Javascript
AngularJS+Node.js实现在线聊天室
Aug 28 Javascript
jQuery基于函数重载实现自定义Alert函数样式的方法
Jul 27 Javascript
AngularJs Modules详解及示例代码
Sep 01 Javascript
jQuery实现点击任意位置弹出层外关闭弹出层效果
Oct 19 Javascript
JS实现自动阅读单词(有道单词本添加功能)
Nov 14 Javascript
JS实现动态修改table及合并单元格的方法示例
Feb 20 Javascript
jQuery 中msgTips 顶部弹窗效果实现代码
Aug 14 jQuery
详解Node.js异步处理的各种写法
Jun 09 Javascript
jquery实现拖拽小方块效果
Dec 10 jQuery
js nextSibling属性和previousSibling属性概述及使用注意
Feb 16 #Javascript
jQuery事件绑定.on()简要概述及应用
Feb 07 #Javascript
10个基于浏览器的JavaScript调试工具分享
Feb 07 #Javascript
利用JQuery动画制作滑动菜单项效果实现步骤及代码
Feb 07 #Javascript
jquery 选择器引擎sizzle浅析
Feb 06 #Javascript
extjs3 combobox取value和text案例详解
Feb 06 #Javascript
js汉字转拼音实现代码
Feb 06 #Javascript
You might like
php中变量及部分适用方法
2008/03/27 PHP
php 批量替换程序的具体实现代码
2013/10/04 PHP
Sublime里直接运行PHP配置方法
2014/11/28 PHP
thinkphp3.2中实现phpexcel导出带生成图片示例
2017/02/14 PHP
Laravel如何使用数据库事务及捕获事务失败后的异常详解
2017/10/23 PHP
php实现mysql连接池效果实现代码
2018/01/25 PHP
javascript 复杂的嵌套环境中输出单引号和双引号
2009/05/26 Javascript
js获取php变量的实现代码
2013/08/10 Javascript
js关于字符长度限制的问题示例探讨
2014/01/24 Javascript
禁止iframe脚本弹出的窗口覆盖了父窗口的方法
2014/09/06 Javascript
jQuery实现字符串按指定长度加入特定内容的方法
2015/03/11 Javascript
nodejs开发微博实例
2015/03/25 NodeJs
javascript实现输出指定行数正方形图案的方法
2015/08/03 Javascript
基于jquery实现左右按钮点击的图片切换效果
2021/01/27 Javascript
基于jQuery实现的双11天猫拆红包抽奖效果
2015/12/01 Javascript
Bootstrap实现下拉菜单效果
2016/04/29 Javascript
用JS动态改变表单form里的action值属性的两种方法
2016/05/25 Javascript
node.js实现快速截图
2016/08/27 Javascript
使用开源工具制作网页验证码的方法
2016/10/17 Javascript
微信小程序 页面跳转如何实现传值
2017/04/05 Javascript
jQuery开源组件BootstrapValidator使用详解
2017/06/29 jQuery
python实现巡检系统(solaris)示例
2014/04/02 Python
黑科技 Python脚本帮你找出微信上删除你好友的人
2016/01/07 Python
Python SqlAlchemy动态添加数据表字段实例解析
2018/02/07 Python
详解Python数据分析--Pandas知识点
2019/03/23 Python
对python中GUI,Label和Button的实例详解
2019/06/27 Python
Python批量启动多线程代码实例
2020/02/18 Python
python 日志 logging模块详细解析
2020/03/31 Python
Python Matplotlib简易教程(小白教程)
2020/07/28 Python
Flask中jinja2的继承实现方法及实例
2021/03/03 Python
Antler英国官网:购买安特丽行李箱、拉杆箱
2019/08/25 全球购物
汽车专业毕业生自荐信
2013/11/03 职场文书
2015年大学生村官工作总结
2015/04/21 职场文书
贫困证明书范文
2015/06/16 职场文书
SQLServer2008提示评估期已过解决方案
2021/04/12 SQL Server
redis 查看所有的key方式
2021/05/07 Redis