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 相关文章推荐
jQuery 跨域访问问题解决方法
Dec 02 Javascript
文本框回车提交与禁止提交示例
Sep 27 Javascript
你未必知道的JavaScript和CSS交互的5种方法
Apr 02 Javascript
node.js中的http.response.end方法使用说明
Dec 14 Javascript
基于jquery实现弹幕效果
Sep 29 Javascript
jQuery基于排序功能实现上移、下移的方法
Nov 26 Javascript
Bootstrap table使用方法详细介绍
Dec 09 Javascript
VUE开发一个图片轮播的组件示例代码
Mar 06 Javascript
jQuery实现所有验证通过方可提交的表单验证
Nov 21 jQuery
ActiveX控件的使用-js实现打印超市小票功能代码详解
Nov 22 Javascript
JavaScript 替换所有匹配内容及正则替换方法
Feb 12 Javascript
Element-ui upload上传文件限制的解决方法
Jan 22 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框架Laravel学习心得体会
2015/10/28 PHP
使用PHP similar text计算两个字符串相似度
2015/11/06 PHP
ThinkPHP框架里隐藏index.php
2016/04/12 PHP
Smarty模板引擎缓存机制详解
2016/05/23 PHP
Laravel 批量更新多条数据的示例
2017/11/27 PHP
PHP实现随机发放扑克牌
2020/04/21 PHP
用jQuery实现检测浏览器及版本的脚本代码
2008/01/22 Javascript
js构造函数、索引数组和属性的实现方式和使用
2014/11/16 Javascript
jQuery中next方法用法实例
2015/04/24 Javascript
基于JavaScript实现通用tab选项卡(通用性强)
2016/01/07 Javascript
利用node.js制作命令行工具方法教程(一)
2017/06/22 Javascript
关于laydate.js加载laydate.css路径错误问题解决
2017/12/27 Javascript
vue 使某个组件不被 keep-alive 缓存的方法
2018/09/21 Javascript
JavaScript 2018 中即将迎来的新功能
2018/09/21 Javascript
js实现图片推拉门效果代码实例
2019/05/18 Javascript
JS 数组基本用法入门示例解析
2020/01/16 Javascript
Python常见字符串操作函数小结【split()、join()、strip()】
2018/02/02 Python
Django后台获取前端post上传的文件方法
2018/05/28 Python
Django中的Model操作表的实现
2018/07/24 Python
python lxml中etree的简单应用
2019/05/10 Python
python实现海螺图片的方法示例
2019/05/12 Python
python django下载大的csv文件实现方法分析
2019/07/19 Python
Python中os模块功能与用法详解
2020/02/26 Python
python计算auc的方法
2020/09/09 Python
python获取时间戳的实现示例(10位和13位)
2020/09/23 Python
HTML+CSS3模拟心的跳动实例代码
2017/09/05 HTML / CSS
Weblogc domain问题
2014/01/27 面试题
Shell如何接收变量输入
2016/08/06 面试题
程序员跳槽必看面试题总结
2013/06/28 面试题
关于旷工的检讨书
2014/02/02 职场文书
丑小鸭教学反思
2014/02/03 职场文书
勾股定理课后反思
2014/04/26 职场文书
卫生院艾滋病宣传活动小结
2014/07/09 职场文书
出售房屋委托书范本
2014/09/24 职场文书
情感电台广播稿
2015/08/18 职场文书
MYSQL如何查看进程和kill进程
2022/03/13 MySQL