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 相关文章推荐
纯JS实现的批量图片预览加载功能
Aug 14 Javascript
window.location.href中url中数据量太大时的解决方法
Dec 23 Javascript
可编辑下拉框的2种实现方式
Jun 13 Javascript
jQuery中data()方法用法实例
Dec 27 Javascript
基于JS代码实现图片在页面中旋转效果
Jun 16 Javascript
通过jsonp获取json数据实现AJAX跨域请求
Jan 22 Javascript
浅谈 vue 中的 watcher
Dec 04 Javascript
Vue项目添加动态浏览器头部title的方法
Jul 11 Javascript
vue.js实现带日期星期的数字时钟功能示例
Aug 28 Javascript
js实现网页同时进行多个倒计时功能
Feb 25 Javascript
ES6之Proxy的get方法详解
Oct 11 Javascript
Vue组件通信中非父子组件传值知识点总结
Dec 05 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中实现用数组妩媚地生成要执行的sql语句
2015/07/10 PHP
Zend Framework入门之环境配置及第一个Hello World示例(附demo源码下载)
2016/03/21 PHP
php使用FFmpeg接口获取视频的播放时长、码率、缩略图以及创建时间
2016/11/07 PHP
JavaScript将相对地址转换为绝对地址示例代码
2013/07/19 Javascript
js读写json文件实例代码
2014/10/21 Javascript
javascript实现网页字符定位的方法
2015/07/14 Javascript
JS根据生日月份和日期计算星座的简单实现方法
2016/11/24 Javascript
详解nodejs微信公众号开发——6.自定义菜单
2017/04/13 NodeJs
vue中用H5实现文件上传的方法实例代码
2017/05/27 Javascript
基于react组件之间的参数传递(详解)
2017/09/05 Javascript
AngularJs 禁止模板缓存的方法
2017/11/28 Javascript
BootStrap table实现表格行拖拽效果
2018/12/01 Javascript
使用react context 实现vue插槽slot功能
2019/07/18 Javascript
vue iview 隐藏Table组件里的某一列操作
2020/11/13 Javascript
读写json中文ASCII乱码问题的解决方法
2016/11/05 Python
Python PyQt5实现的简易计算器功能示例
2017/08/23 Python
Python父目录、子目录的相互调用方法
2019/02/16 Python
详解python持久化文件读写
2019/04/06 Python
python实现知乎高颜值图片爬取
2019/08/12 Python
Django关于admin的使用技巧和知识点
2020/02/10 Python
解决python中显示图片的plt.imshow plt.show()内存泄漏问题
2020/04/24 Python
python使用scapy模块实现ARP扫描的过程
2021/01/21 Python
利用python实现汉诺塔游戏
2021/03/01 Python
html5实现多图片预览上传及点击可拖拽控件
2018/03/15 HTML / CSS
美国在线购买内衣网站:HerRoom
2020/02/22 全球购物
RealTek面试题
2016/06/28 面试题
函授本科个人自我鉴定
2014/03/25 职场文书
客户答谢会活动方案
2014/08/31 职场文书
计划生育证明书写要求
2014/09/17 职场文书
创先争优个人总结
2015/03/04 职场文书
2015年学校体育工作总结
2015/04/22 职场文书
幼儿园开学通知
2015/04/24 职场文书
鸦片战争观后感
2015/06/09 职场文书
描写九月优美句子(39条)
2019/09/11 职场文书
关于企业的执行力标语大全
2020/01/06 职场文书
Python中生成随机数据安全性、多功能性、用途和速度方面进行比较
2022/04/14 Python