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 相关文章推荐
javascript KeyDown、KeyPress和KeyUp事件的区别与联系
Dec 03 Javascript
js原型继承的两种方法对比介绍
Mar 30 Javascript
jquery实现的树形目录实例
Jun 26 Javascript
javascript自定义in_array()函数实现方法
Aug 03 Javascript
Bootstrap每天必学之按钮(Button)插件
Apr 25 Javascript
jQuery实现自动输入email、时间和域名的方法
Aug 24 Javascript
headjs实现网站并行加载但顺序执行JS
Nov 29 Javascript
vue学习笔记之指令v-text &amp;&amp; v-html &amp;&amp; v-bind详解
May 12 Javascript
jQuery+Ajax请求本地数据加载商品列表页并跳转详情页的实现方法
Jul 12 jQuery
JavaScript使用小插件实现倒计时的方法讲解
Mar 11 Javascript
vue 监听窗口变化对页面部分元素重新渲染操作
Jul 28 Javascript
使用JS实现鼠标放上图片进行放大离开实现缩小功能
Jan 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中处理mysql_fetch_assoc返回来的数组 不用foreach----echo
2011/05/04 PHP
php实现通过cookie换肤的方法
2015/07/13 PHP
thinkphp3.x中session方法的用法分析
2016/05/20 PHP
PHP封装的page分页类定义与用法完整示例
2018/12/24 PHP
PHP crc32()函数讲解
2019/02/14 PHP
JScript的条件编译
2007/05/29 Javascript
jquery多浏览器捕捉回车事件代码
2010/06/22 Javascript
转换json格式的日期为Javascript对象的函数
2010/07/13 Javascript
JS实现很酷的EMAIL地址添加功能实例
2015/02/28 Javascript
Node.js中的流(Stream)介绍
2015/03/30 Javascript
如何动态加载外部Javascript文件
2015/12/02 Javascript
javascript作用域、作用域链(菜鸟必看)
2016/06/16 Javascript
Bootstrap超大屏幕的实现代码
2017/03/22 Javascript
微信网页授权并获取用户信息的方法
2018/07/30 Javascript
详解Vue.js v-for不支持IE9的解决方法
2018/12/29 Javascript
Jquery实现无缝向上循环滚动列表的特效
2019/02/13 jQuery
spring+angular实现导出excel的实现代码
2019/02/27 Javascript
配置eslint规范项目代码风格
2019/03/11 Javascript
微信小程序组件生命周期的踩坑记录
2021/03/03 Javascript
Python深入学习之上下文管理器
2014/08/31 Python
跟老齐学Python之私有函数和专有方法
2014/10/24 Python
python对html代码进行escape编码的方法
2015/05/04 Python
Python的randrange()方法使用教程
2015/05/15 Python
Python Django 页面上展示固定的页码数实现代码
2019/08/21 Python
python实现超市商品销售管理系统
2019/10/25 Python
pytorch载入预训练模型后,实现训练指定层
2020/01/06 Python
python查询MySQL将数据写入Excel
2020/10/29 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
ECCO俄罗斯官网:北欧丹麦鞋履及皮具品牌
2020/06/26 全球购物
国外的一些J2EE面试题一
2012/10/13 面试题
财务总经理岗位职责
2014/02/16 职场文书
搞笑老公保证书
2015/02/26 职场文书
警示教育片观后感
2015/06/17 职场文书
小学三年级语文教学反思
2016/03/03 职场文书
全家福照片寄语怎么写?
2019/04/02 职场文书
vue router 动态路由清除方式
2022/05/25 Vue.js