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 相关文章推荐
自定义函数实现IE7与IE8不兼容js中trim函数的问题
Feb 03 Javascript
js关于命名空间的函数实例
Feb 05 Javascript
jQuery使用toggleClass方法动态添加删除Class样式的方法
Mar 26 Javascript
BootStrap实用代码片段之一
Mar 22 Javascript
浅谈$('div a') 与$('div&gt;a')的区别
Jul 18 Javascript
JavaScript兼容浏览器FF/IE技巧
Aug 14 Javascript
原生JS实现N级菜单的代码
May 21 Javascript
Node.js操作redis实现添加查询功能
May 25 Javascript
vue2.0在table中实现全选和反选的示例代码
Nov 04 Javascript
Javascript网页抢红包外挂实现分享
Jan 11 Javascript
pm2启动ssr失败的解决方法
Jun 29 Javascript
解决vue项目运行npm run serve报错的问题
Oct 26 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下将XML转换为数组
2010/01/01 PHP
php常用表单验证类用法实例
2015/06/18 PHP
JS类定义原型方法的两种实现的区别评论很多
2007/09/12 Javascript
JavaScript 异步调用框架 (Part 6 - 实例 &amp; 模式)
2009/08/04 Javascript
跨域表单提交状态的变相判断代码
2009/11/12 Javascript
jquery 模拟类搜索框自动完成搜索提示功能(改进)
2010/05/24 Javascript
关于this和self的使用说明
2010/08/01 Javascript
JQuery实现的购物车功能(可以减少或者添加商品并自动计算价格)
2015/01/13 Javascript
jQuery Ajax调用WCF服务详细教程
2015/03/31 Javascript
ubuntu下安装nodejs以及升级的办法
2015/05/08 NodeJs
easyui导出excel无法弹出下载框的快速解决方法
2016/11/10 Javascript
bootstrap提示标签、提示框实现代码
2016/12/28 Javascript
理解 JavaScript EventEmitter
2018/03/29 Javascript
Vue render深入开发讲解
2018/04/13 Javascript
vue实现商品加减计算总价的实例代码
2018/08/12 Javascript
JS实现的tab页切换效果完整示例
2018/12/18 Javascript
微信小程序里引入SVG矢量图标的方法
2019/09/20 Javascript
vue+element表格导出为Excel文件
2019/09/26 Javascript
[00:32]2018DOTA2亚洲邀请赛出场——LGD
2018/04/04 DOTA
[01:15:15]VG VS EG Supermajor小组赛B组胜者组第一轮 BO3第二场 6.2
2018/06/03 DOTA
详解python中requirements.txt的一切
2017/03/03 Python
Python中index()和seek()的用法(详解)
2017/04/27 Python
pygame实现简易飞机大战
2018/09/11 Python
利用pandas合并多个excel的方法示例
2019/10/10 Python
python实现录屏功能(亲测好用)
2020/03/02 Python
adidas菲律宾官网:adidas PH
2020/02/07 全球购物
加拿大拼图大师:Puzzle Master
2020/12/28 全球购物
英国健身专家:WIT Fitness
2021/02/09 全球购物
如何向接受结构参数的函数传入常数值
2016/02/17 面试题
诚信承诺书范文
2014/03/27 职场文书
《闻一多先生的说和做》教学反思
2014/04/28 职场文书
小学家长学校培训材料
2014/08/24 职场文书
2014年数学教师工作总结
2014/12/03 职场文书
2014年财务个人工作总结
2014/12/08 职场文书
庆祝教师节主题班会
2015/08/17 职场文书
《倍数和因数》教学反思
2016/02/23 职场文书