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 concat数组累加 示例
Sep 03 Javascript
jquery animate 动画效果使用说明
Nov 04 Javascript
javascript时间自动刷新实现原理与步骤
Jan 06 Javascript
通过Javascript读取本地Excel文件内容的代码示例
Apr 08 Javascript
JavaScript中获取高度和宽度函数总结
Oct 08 Javascript
Jquery插件实现点击获取验证码后60秒内禁止重新获取
Mar 13 Javascript
JS封装cookie操作函数实例(设置、读取、删除)
Nov 17 Javascript
jQuery实现可移动选项的左右下拉列表示例
Dec 26 Javascript
微信小程序实现上传图片功能
May 28 Javascript
浅谈Vue.js组件(二)
Apr 09 Javascript
jquery+ajax实现上传图片并显示上传进度功能【附php后台接收】
Jun 06 jQuery
JavaScript隐式类型转换代码实例
May 29 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+SqlServer实现分页显示
2006/10/09 PHP
使用gd库实现php服务端图片裁剪和生成缩略图功能分享
2013/12/25 PHP
thinkPHP下ueditor的使用方法详解
2015/12/26 PHP
WordPress开发中的get_post_custom()函数使用解析
2016/01/04 PHP
PHP文件操作简单介绍及函数汇总
2020/12/11 PHP
写出更好的JavaScript程序之undefined篇(中)
2009/11/23 Javascript
自写简单JS判断是否已经弹出页面
2010/10/20 Javascript
jquery 学习之二 属性相关
2010/11/23 Javascript
Jquery中对数组的操作代码
2011/08/12 Javascript
最佳的addEvent事件绑定是怎样诞生的
2011/10/24 Javascript
javascript中将Object转换为String函数代码 (json str)
2012/04/29 Javascript
使用js简单实现了tree树菜单
2013/11/20 Javascript
jquery实现弹出层完美居中效果
2014/03/03 Javascript
jquery选择器排除某个DOM元素的方法(实例演示)
2014/04/25 Javascript
JS按回车键实现登录的方法
2014/08/25 Javascript
js实现三张图(文)片一起切换的banner焦点图
2015/08/25 Javascript
js css自定义分页效果
2017/02/24 Javascript
discuz表情的JS提取方法分析
2017/03/22 Javascript
Node.js v8.0.0正式发布!看看带来了哪些主要新特性
2017/06/02 Javascript
Angular.JS中指令ng-if的注意事项小结
2017/06/21 Javascript
vue 封装自定义组件之tabal列表编辑单元格组件实例代码
2017/09/07 Javascript
vue渲染时闪烁{{}}的问题及解决方法
2018/03/28 Javascript
Vue.set() this.$set()引发的视图更新思考及注意事项
2018/08/30 Javascript
[01:02:32]DOTA2-DPC中国联赛 正赛 iG vs PSG.LGD BO3 第二场 2月26日
2021/03/11 DOTA
基于Python实现的ID3决策树功能示例
2018/01/02 Python
Python学习笔记之函数的定义和作用域实例详解
2019/08/13 Python
python GUI库图形界面开发之PyQt5菜单栏控件QMenuBar的详细使用方法与实例
2020/02/28 Python
python画图常规设置方式
2020/03/05 Python
更新升级python和pip版本后不生效的问题解决
2020/04/17 Python
Python -m参数原理及使用方法解析
2020/08/21 Python
Python3中的tuple函数知识点讲解
2021/01/03 Python
CSS3制作轮播图的一种方法
2019/11/11 HTML / CSS
经典演讲稿范文
2013/12/30 职场文书
大型车展策划方案
2014/02/01 职场文书
利用Python判断你的密码难度等级
2021/06/02 Python
html用代码制作虚线框怎么做? dw制作虚线圆圈的技巧
2022/12/24 HTML / CSS