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 相关文章推荐
很可爱的输入框
Aug 03 Javascript
24款非常有用的 jQuery 插件分享
Apr 06 Javascript
jQuery调用WebService的实现代码
Jun 19 Javascript
jquery遍历数组与筛选数组的方法
Nov 05 Javascript
浅谈 jQuery 事件源码定位问题
Jun 18 Javascript
原生js实现日期联动
Jan 12 Javascript
JavaScript实现按照指定长度为数字前面补零输出的方法
Mar 19 Javascript
Javascript闭包与函数柯里化浅析
Jun 22 Javascript
基于vue配置axios的方法步骤
Nov 09 Javascript
深入理解vue中slot与slot-scope的具体使用
Jan 26 Javascript
详解vue更改头像功能实现
Apr 28 Javascript
在SSM框架下用laypage和ajax实现分页和数据交互的方法
Sep 27 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实现简单数字分页效果
2015/07/26 PHP
又十个超级有用的PHP代码片段
2015/09/24 PHP
php验证码的制作思路和实现方法
2015/11/12 PHP
PHP异常处理Exception类
2015/12/11 PHP
php编译安装php-amq扩展简明教程
2016/06/25 PHP
如何在PHP中读写文件
2020/09/07 PHP
语义化 H1 标签
2008/01/14 Javascript
基于jquery的内容循环滚动小模块(仿新浪微博未登录首页滚动微博显示)
2011/03/28 Javascript
jQuery 源码分析笔记(5) jQuery.support
2011/06/19 Javascript
c#和Javascript操作同一json对象的实现代码
2012/01/17 Javascript
解决遍历时Array.indexOf产生的性能问题
2012/07/03 Javascript
js控制滚动条缓慢滚动到顶部实现代码
2013/03/20 Javascript
javascript代码运行不出来执行错误的可能情况整理
2013/10/18 Javascript
JavaScript实现继承的4种方法总结
2014/10/16 Javascript
三种AngularJS中获取数据源的方式
2016/02/02 Javascript
JS跨域请求外部服务器的资源
2017/02/06 Javascript
详谈JS中数组的迭代方法和归并方法
2017/08/11 Javascript
详解javascript中的变量提升和函数提升
2018/05/24 Javascript
JS面向对象编程基础篇(一) 对象和构造函数实例详解
2020/03/03 Javascript
python基于itchat实现微信群消息同步机器人
2017/02/27 Python
Python 自动刷博客浏览量实例代码
2017/06/14 Python
Python爬虫实例爬取网站搞笑段子
2017/11/08 Python
python清理子进程机制剖析
2017/11/23 Python
示例详解Python3 or Python2 两者之间的差异
2018/08/23 Python
python 列表推导式使用详解
2019/08/29 Python
python日期与时间戳的各种转换示例
2020/02/12 Python
Python如何实现自带HTTP文件传输服务
2020/07/08 Python
浅谈CSS3中的变形功能-transform功能
2017/12/27 HTML / CSS
HTML5的语法变化介绍
2013/08/13 HTML / CSS
经济与贸易专业应届生求职信
2013/11/19 职场文书
英文简历自荐信范文
2013/12/11 职场文书
《充气雨衣》教学反思
2014/04/07 职场文书
出生证明公证书
2014/04/09 职场文书
幸福中国演讲稿
2014/09/12 职场文书
网络营销计划书
2015/01/17 职场文书
APP界面设计技巧和注意事项
2022/04/29 杂记