JavaScript调用堆栈及setTimeout使用方法深入剖析

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函数调用的灵活性,为函数执行顺序的调度提供极大便利。

时间: 2013-02-14

java自带的工具Jstack截取进程中的堆栈信息

在Java软件的使用过程中,有时会莫名的出现奇怪的问题.而这些问题常常无法使用日志信息定位,这时我们就需要通过查看进程内部线程的堆栈调用关系来分析问题出在哪里. 举个例子,当我们在做某个操作时,莫名的会弹出多个警告框,其中有些信息是正常的,有些则不是.对于这些错误的警告信息,我们该如何定位是哪个位置的代码出现了错误弹出的框呢? 我们就需要在弹框以后,去查看软件的各个线程,去查找究竟是哪个线程导致了该问题.可是有时因为环境.时间等问题,我们根本不能拿着IDE去调试, 只能通过工具软件拍下内存快照,

JavaScript错误处理和堆栈追踪详解

有时我们会忽略错误处理和堆栈追踪的一些细节, 但是这些细节对于写与测试或错误处理相关的库来说是非常有用的. 例如这周, 对于 Chai 就有一个非常棒的PR, 该PR极大地改善了我们处理堆栈的方式, 当用户的断言失败的时候, 我们会给予更多的提示信息(帮助用户进行定位). 合理地处理堆栈信息能使你清除无用的数据, 而只专注于有用的数据. 同时, 当更好地理解 Errors 对象及其相关属性之后, 能有助于你更充分地利用 Errors. (函数的)调用栈是怎么工作的 在谈论错误之前, 先要了解下(

Javascript 错误处理的几种方法

1.使用window.onerror指定错误处理函数. 当有错误的时候,onerror会被callback. 当某个JavaScript block中有多个script错误时,第一个错误触发后(回调callback),当前Javascript block后面的script会被自动Drop忽略掉,不被执行. 如:  复制代码 代码如下: <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>

javascript Error 对象 错误处理

Error对象 Property:   name: 错误名   number: 错误号   description: 描述   message: 错误信息,多同description  FF Only 属性   fileName: 错误发生的文件   stack: 错误发生时的调用堆栈 Constructor:   Error(){     this(0,"")} Error(description){     this(0,description)} Error(number,des

JS实现队列与堆栈的方法

本文实例讲述了JS实现队列与堆栈的方法.分享给大家供大家参考,具体如下: 在面向对象的程序设计里,一般都提供了实现队列(queue)和堆栈(stack)的方法,而对于JS来说,我们可以实现数组的相关操作,来实现队列和堆栈的功能,看下面的相关介绍. 一.看一下它们的性质,这种性质决定了它们的使用场合 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被取出! 堆栈:是一种支持后进先出(LIFO)的集合,即后被插入的数据,先被取出! 二.看一下实现的代码(JS代码) var a=new

JavaScript 错误处理与调试经验总结

下面总结一下JS错误处理与调试的方法 方法1:用alert() 和document.write()方法监视变量值. alert()在弹出对话框显示变量值的同时,会停止代码的继续运行,直到用户单击"确定"按钮,而document.write()则在输出值后继续运行代码.调试JS时可以根据具体情况来选择这种方法. 例如下面代码:将数组a中以1开头的数据添加到数组b中 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.

JavaScript高级程序设计 错误处理与调试学习笔记

第十四章 错误处理与调试 1.开启浏览器错误报告 1.1 Internet Explorer □Toos → Internet Option → Anvanced → Display a notification about every script error 1.2 Firefox □Tools → Error Console (Firebug) 1.3 Safari □Edit → Preferences → Advanced → Show develop menu in menubar/

输出java进程的jstack信息示例分享 通过线程堆栈信息分析java线程

复制代码 代码如下: #!/bin/shpro_name=java #process namekeys=`ps -ef |grep "$pro_name" |grep -v "grep" | awk '{print $2}'`nowdate=`date +%Y%m%d%H%M%S` jstackpath="/usr/java/jdk1.6.0_07/bin/jstack"cpulogpath="/home/" for key

JavaScript错误处理

一.错误分类 1. 语法错误 也称为解析错误,发生在传统编程语言的编译时,在JavaScript中发生在解释时,这些错误是由代码中的意外字符直接引起的,然后就不能直接编译/解释,eg,在一行代码因缺少右括号,产生了语法错误.发生语法错误时,就不能继续执行代码.在JavaScript中,只有在同一个线程中的代码会受语法错误的影响.在其他线程中的代码和其他外部引用的文件中的代码,如果不依赖于包含错误的代码,则可以继续执行. 2. 运行时错误 也称为异常(exception,在编译期/解释器后).此时

JavaScript高级程序设计 阅读笔记(二十) js错误处理

一.错误分类 1.语法错误:也称解析错误,发生在传统语言的编译时,在JavaScript中发生在解释时.这些错误是由代码中的意外字符直接引起的,然后就不能直接编译/解释.发生语法错误时,就不能继续执行代码.在JavaScript中,只有在同一个线程中的代码会受语法错误的影响.在其他线程中的代码和其他外部引用的文件中的代码,如果不依赖于包含错误的代码,则可以继续执行. 2.运行时错误:也称为异常(exception,在编译期/解释器后).此时,问题并不出在代码的语法上,而是,尝试完成的一个操作,在

JavaScript高级程序设计 阅读笔记(十二) js内置对象Math

Math对象的属性 E:值e,自然对数的底 LN10:10的自然对数 LN2:2的自然对数 LOG2E:以2为底E的对数 LOG10E:以10为底E的对数 PI:值派 SQRT1_2:1/2 的平方根 SQRT2:2的平方根 Math对象的方法:最大值与最小值 min()&&max()用于取一组数中的最小值跟最大值. 示例: 复制代码 代码如下: var iMax=Math.Max(1,2,3); alert(iMax);//outputs 3 var iMin=Math.Min(1,2,

JavaScript高级程序设计 阅读笔记(十九) js表格排序

排序代码 复制代码 代码如下: function SortTable(sTableID, iCol, sDataType){ this.oTable=document.getElementById(sTableID); this.oTBody=this.oTable.tBodies[0]; this.colDataRows=this.oTBody.rows; this.aTRs=[]; this.iCol=iCol; this.sDataType=sDataType; } SortTable.p

JavaScript高级程序设计阅读笔记(十六) javascript检测浏览器和操作系统-detect.js

检测浏览器的方式 1.对象特征检测法:判断浏览器能力的通用方法.如果更关注浏览器的能力而不在乎它的实际身份,就可以使用这种检测方法.常见的原生Ajax写法中就用这种方法来创建XMLHttpRequest: 复制代码 代码如下: IXHR: function(){ if(window.ActiveXObject){ XHR=new ActiveXObject('Microsoft.XMLHTTP'); }else if(window.XMLHttpRequest){ XHR=new XMLHttp

JavaScript高级程序设计 阅读笔记(十四) js继承机制的实现

继承 继承是面向对象语言的必备特征,即一个类能够重用另一个类的方法和属性.在JavaScript中继承方式的实现方式主要有以下五种:对象冒充.call().apply().原型链.混合方式. 下面分别介绍. 对象冒充 原理:构造函数使用this关键字给所有属性和方法赋值.因为构造函数只是一个函数,所以可以使ClassA的构造函数成为ClassB的方法,然后调用它.ClassB就会收到ClassA的构造函数中定义的属性和方法. 示例: 复制代码 代码如下: function ClassA(sCol

JavaScript高级程序设计 阅读笔记(十八) js跨平台的事件

跨平台的事件EventUtil对象 EventUtil: 复制代码 代码如下: var EventUtil={ addEventHandler:function(oTarget, sEventType, fnHandler){ if(oTarget.addEventListener){ oTarget.addEventListener(sEventType,fnHandler,false); } else if(oTarget.attachEvent){ oTarget.attachEvent(

JavaScript高级程序设计 阅读笔记(十五) 浏览器中的JavaScript

Window对象 窗口操作 Window对象对操作浏览器窗口非常有用,开发者可以移动或调整浏览器窗口的大小.可用四种方法实现这些操作: moveBy(dx,dy):把浏览器窗口相对当前位置水平移动dx个像素,垂直移动dy个像素.dx值为负左移,dy为负上移. moveTo(x,y):移动浏览器窗口,使它的左上角位于用户屏幕的(x,y)处.可以使用负数,不过这样会把部分窗口移出屏幕的可视区域. resizeBy(dw,dh):相对浏览器窗口当前大小,把窗口的宽度调整dw个像素,高度调整dy个像素.

JavaScript高级程序设计 阅读笔记(十七) js事件

一.事件流 IE中是冒泡型事件,即从最特定的事件目标到最不特定的事件目标. Netscape Navigator使用的是捕获型事件,这个跟IE中采用的冒泡型事件相反. DOM事件流同时支持两种事件模型,但捕获型事件先发生. 二.事件处理函数/监听函数 事件是用户或浏览器自身进行的特定行为.这些事件都有自己的名字,如click.load.mouseover等. 事件处理函数有两种分配方式:在JavaScript中或者在HTML中. 如果在JavaScript中分配事件处理函数,则首先要获得要处理的

JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML

一.IE中的XML DOM支持 IE对XML的支持是基于ActiveX的MSXML库. 1.DOM创建 对每个新版本的MSXML,都会创建出不同的XML DOM对象,所以尽量选择新的XML DOM版本. 2.载入XML 载入XML分两种,即: 载入XML字符串:loadXML(xml字符串) 载入xml文件:load(xml文件路径).默认情况下文件载入是异步的,如果要改为同步把asynce特性改为true即可.异步载入文件时要用到readyState和onreadystatechange事件处

JavaScript高级程序设计 阅读笔记(十三) js定义类或对象

工厂方式 创建并返回特定类型的对象. 复制代码 代码如下: function createCar(sColor,iDoors,iMpg){ var oTempCar=new Object(); oTempCar.color=sColor; oTempCar.doors=iDoors; oTempCar.mpg=iMpg; oTempCar.showColor=function(){ alert(this.color); } return oTempCar; } 调用示例: 复制代码 代码如下: