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 相关文章推荐
高亮显示web页表格行的javascript代码
Nov 19 Javascript
40个有创意的jQuery图片、内容滑动及弹出插件收藏集之一
Dec 31 Javascript
超棒的响应式布局jQuery插件Freetile.js
Nov 17 Javascript
JavaScript中的eval()函数使用介绍
Dec 31 Javascript
jQuery中not()方法用法实例
Jan 06 Javascript
JS模仿编辑器实时改变文本框宽度和高度大小的方法
Aug 17 Javascript
js精美的幻灯片画集特效代码分享
Aug 29 Javascript
第四篇Bootstrap网格系统偏移列和嵌套列
Jun 21 Javascript
jQuery实现左侧导航模块的显示与隐藏效果
Jul 04 Javascript
JS判断是否手机或pad访问实现方法
Dec 09 Javascript
JS倒计时实例_天时分秒
Aug 22 Javascript
浅析vue中常见循环遍历指令的使用 v-for
Apr 18 Javascript
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里的JS打印函数
2006/10/09 PHP
收藏的一个php小偷的核心程序
2007/04/09 PHP
php Rename 更改文件、文件夹名称
2011/05/24 PHP
php中json_encode处理gbk与gb2312中文乱码问题的解决方法
2014/07/10 PHP
destoon数据库表说明汇总
2014/07/15 PHP
Yii控制器中filter过滤器用法分析
2016/07/15 PHP
django中的ajax组件教程详解
2018/10/18 PHP
Laravel 数据库加密及数据库表前缀配置方法
2019/10/10 PHP
PHPUnit + Laravel单元测试常用技能
2019/11/06 PHP
IE7中javascript操作CheckBox的checked=true不打勾的解决方法
2009/12/07 Javascript
基于Jquery的简单图片切换效果
2011/01/06 Javascript
jQuery中的val()示例应用
2014/02/26 Javascript
javascript 获取HTML DOM父、子、临近节点
2014/06/16 Javascript
JS使用正则表达式除去字符串中重复字符的方法
2015/11/05 Javascript
jquery实现全屏滚动
2015/12/28 Javascript
基于JS实现导航条flash导航条
2016/06/17 Javascript
微信小程序(应用号)开发新闻客户端实例
2016/10/24 Javascript
用jQuery的AJax实现异步访问、异步加载
2016/11/02 Javascript
JS实现根据用户输入分钟进行倒计时功能
2016/11/14 Javascript
JQueryEasyUI框架下的combobox的取值和绑定的方法
2017/01/22 Javascript
微信小程序 五星评价功能的实现
2017/03/09 Javascript
javascript+html5+css3自定义弹出窗口效果
2017/10/26 Javascript
JS实现带动画的回到顶部效果
2017/12/28 Javascript
详解vue的diff算法原理
2018/05/20 Javascript
JS中实现隐藏部分姓名或者电话号码的代码
2018/07/17 Javascript
python机器学习包mlxtend的安装和配置详解
2019/08/21 Python
python多线程爬取西刺代理的示例代码
2021/01/30 Python
Geekbuying波兰:购买中国电子产品
2019/10/20 全球购物
中学生校园广播稿
2014/01/16 职场文书
安全责任协议书
2014/04/21 职场文书
法人授权委托书样本
2014/09/19 职场文书
springboot用户数据修改的详细实现
2022/04/06 Java/Android
Win11开始菜单添加休眠选项
2022/04/19 数码科技
win10如何更改appdata文件夹的默认位置?
2022/07/15 数码科技
LeetCode189轮转数组python示例
2022/08/05 Python
Python  序列化反序列化和异常处理的问题小结
2022/12/24 Python