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开发包大全整理
Dec 22 Javascript
JavaScript让IE浏览器event对象符合W3C DOM标准
Nov 24 Javascript
Javascript load Page,load css,load js实现代码
Mar 31 Javascript
jQuery实现的指纹扫描效果实例(附演示与demo源码下载)
Jan 26 Javascript
jQuery中的基本选择器用法学习教程
Apr 14 Javascript
js实现纯前端的图片预览
Apr 27 Javascript
JS使用正则表达式实现关键字替换加粗功能示例
Aug 03 Javascript
微信小程序 chooseImage选择图片或者拍照
Apr 07 Javascript
js序列化和反序列化的使用讲解
Jan 19 Javascript
基于JS实现前端压缩上传图片的实例代码
May 14 Javascript
jQuery实现图片切换效果
Oct 19 jQuery
js实现简单商品筛选功能
Feb 02 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 mssql 分页SQL语句优化 持续影响
2009/04/26 PHP
PHP面向对象程序设计之类与反射API详解
2016/12/02 PHP
基于PHP实现的多元线性回归模拟曲线算法
2018/01/30 PHP
仅Firefox中链接A无法实现模拟点击以触发其默认行为
2011/07/31 Javascript
IE6下opacity与JQuery的奇妙结合
2013/03/01 Javascript
javascript实现仿IE顶部的可关闭警告条
2015/05/05 Javascript
web前端开发upload上传头像js示例代码
2016/10/22 Javascript
详解Jquery 遍历数组之$().each方法与$.each()方法介绍
2017/01/09 Javascript
ionic实现下拉刷新载入数据功能
2017/05/11 Javascript
angularjs $http实现form表单提交示例
2017/06/09 Javascript
vue.js整合mint-ui里的轮播图实例代码
2017/12/27 Javascript
基于vue展开收起动画的示例代码
2018/07/05 Javascript
Jquery和CSS实现选择框重置按钮功能
2018/11/08 jQuery
基于JS实现前端压缩上传图片的实例代码
2019/05/14 Javascript
vue 动态创建组件的两种方法
2020/12/31 Vue.js
[02:49]2018DOTA2亚洲邀请赛主赛事决赛日战况回顾 Mineski鏖战5局夺得辉耀
2018/04/10 DOTA
Python中函数的用法实例教程
2014/09/08 Python
Python中对象的引用与复制代码示例
2017/12/04 Python
python中Apriori算法实现讲解
2017/12/10 Python
Python操作Sql Server 2008数据库的方法详解
2018/05/17 Python
详解Django+Uwsgi+Nginx 实现生产环境部署
2018/11/06 Python
python多进程读图提取特征存npy
2019/05/21 Python
Django配置MySQL数据库的完整步骤
2019/09/07 Python
使用Python给头像戴上圣诞帽的图像操作过程解析
2019/09/20 Python
python编写猜数字小游戏
2019/10/06 Python
FFT快速傅里叶变换的python实现过程解析
2019/10/21 Python
pytorch 图像中的数据预处理和批标准化实例
2020/01/15 Python
python实现时间序列自相关图(acf)、偏自相关图(pacf)教程
2020/06/03 Python
详解python with 上下文管理器
2020/09/02 Python
python中HTMLParser模块知识点总结
2021/01/25 Python
统计每一学生的平均成绩
2014/06/06 面试题
小学毕业感言500字
2014/02/28 职场文书
《欢乐的泼水节》教学反思
2014/04/22 职场文书
公司担保书格式范文
2014/05/12 职场文书
2015年上半年信访工作总结
2015/03/30 职场文书
管理者们如何制定2019年的工作计划?
2019/07/01 职场文书