继前篇 谈谈JavaScrip的异步实现,我们知道JavaScript引擎是单线程的,所有的js的代码都将在这个单线程中执行。像浏览器事件、计时器等异步只是个幌子,异步时js并没有多个线程在执行,而是都排列在一个待执行队伍中。

setTimeout的使用方法

setTimeout(function(){},time)--可以正确执行。

setTimeout("js语句",time)--可以正确执行。 js语句可以是多条语句。

setTimeout(fun,time)

只引用函数名字,也可运行,但是要注意的是:如果fun是某个对象的方法,则fun函数内的this此时被当做window。

eg:

var obj ={"p1": "obj的属性p1","fun": function() {alert(this.p1);}
};setTimeout(obj.fun,1000);

运行后的结果,是undefined。用函数式对象定义对象也是此种结果。用方法1则可以输出正确的结果。

setTimeout(fun(),time)--不正确使用

不能正确执行,因为fun()会立即执行,没有延迟time时间后执行。

执行时机

当页面初始化时,setTimeout与setInterval的回调与队列中其它回调执行次序是怎样的?《JavaScript权威指南》中介绍的,setTimeout的回调发生在所有的事件都处理完,这句到底是不是对的?带着这些疑问,我们先来看个例子:

1 <!DOCTYPE html>
2 <html>
3 <head>
4     <title></title>
5     <metahttp-equiv="content-type"content="text/html;charset=utf-8">
6     <scripttype="text/javascript"src="a.js"></script>
7     <scripttype="text/javascript">
8         varbefore_x= 2;9     </script>
10     <scripttype="text/javascript">
11         varmiddle_x=3;12         //页面head中js执行完毕后,执行队列(页面尾部的js,定时器回调、事件回调,究竟哪个先执行,这个随机的);
13 setTimeout(function(){14 console.log("Timeout:"+(ax+before_x+middle_x+middle_y+bx+cx+domLoad_x+inner_x));15 },0);16         varinter=setInterval(function(){17 console.log("Interval:"+(ax+before_x+middle_x+middle_y+bx+inner_x+domLoad_x+cx));18 clearInterval(inter);19 },1)20         varmiddle_y=1;21     </script>
22     <scripttype="text/javascript"src="b.js"></script>
23 </head>
24 <body>
25      <inputtype="text"id="inp_click"onclick="inner_x =1;for(var i=0;i<1000000;i++){inner_x++};console.log('clickEvent:'+inner_x);">
26 </body>
27 </html>
28 <scripttype="text/javascript"src="c.js"></script>
29         <scripttype="text/javascript">
30             varstart_time= newDate().getTime();31             for(vari= 1;i<1000000;i++){32
33 }34             varend_time= newDate().getTime();35 console.log('after the html,wait:'+(end_time-start_time));36             varinp=document.getElementById("inp_click");37             varevent=document.createEvent("MouseEvent");38 event.initMouseEvent("click",true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null);39 inp.dispatchEvent(event);40             vardomLoad_x= 4;41         </script>

  a.js

1  var ax =1;

  b.js

1  var bx = 2;

  c.js

1 var cx =3;

chrome中绝大数执行正常;

偶尔会报错,特别是在页面刚在浏览器中打开时,出现以下错误

为什么正常?这是因为计时器在所有的js都执行完后才执行,包括页面尾部的js,模拟触发的事件回调。

为什么报错?这是因为计时器在页面尾部js执行前,先执行。

结论:页面head中js执行完毕后,执行队列(页面尾部的js,定时器回调、事件回调),究竟哪个先执行,这个随机的。《JavaScript高级程序设计》介绍到DomContentLoaded事件时,提到了setTimeout(function(){  //此处添加事件处理程序代码},0);用以弥补老式浏览器不支持DomContentLoaded。

如果你们还有兴趣,我们再来看个例子,至于为什么是这样,大家自己去思考。
1 <!DOCTYPE html>
2 <html>
3 <head>
4     <title></title>
5     <metahttp-equiv="content-type"content="text/html;charset=utf-8">
6     <scripttype="text/javascript"src="a.js"></script>
7     <scripttype="text/javascript">
8         varbefore_x= 2;9 (function(window, undefined) {10             varreadyList=[],11 isReady= 0,12 readyBound= false,13 init,14 bindReady,15 readyWait= 1;16 init= function(wait) {//A third-party is pushing the ready event forwards
17                 if(wait=== true) {18 readyWait--;19 }//Make sure that the DOM is not already loaded
20                 if(!readyWait||(wait!== true && !isReady)) {//Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
21                     //确保body元素存在,这个操作是防止IE的bug
22                     if(!document.body) {23                         returnsetTimeout(init,1);24 }//dom渲染完成标志设置为true
25 isReady= true;//If a normal DOM Ready event fired, decrement, and wait if need be
26                     if(wait!== true && --readyWait> 0) {27                         return;28 }//绑定的渲染完成后的执行函数
29                     if(readyList) {//全部执行
30                         varfn, i= 0,31 ready=readyList;//重置
32 readyList= null;33                         while((fn=ready[i++])) {34 fn.call(document);35 }36 }37 }38 };//初始化readyList事件处理函数队列
39             //兼容不同浏览对绑定事件的区别
40 bindReady= function() {41                 if(readyBound) {42                     return;43 }44 readyBound= true;//$(document).ready()的嵌套调用时
45                 //readyState: "uninitalized"、"loading"、"interactive"、"complete" 、"loaded"
46                 if(document.readyState=== "complete") {//让它异步执行,使这个ready能延迟
47                     returnsetTimeout(init,1);48 }//Mozilla, Opera and webkit
49                 //兼容事件,通过检测浏览器的功能特性,而非嗅探浏览器
50                 if(document.addEventListener) {//使用事件回调函数
51 document.addEventListener("DOMContentLoaded",52                             function() {53 document.removeEventListener("DOMContentLoaded", arguments.callee,false);54 init();55 },56                             false);//绑定回调到load,使之能一定执行
57 window.addEventListener("load", init,false);//IE
58 }else if(document.attachEvent) {//确保在load之前触发onreadystatechange,
59                     //针对iframe情况,可能有延迟
60 document.attachEvent("onreadystatechange",61                             function() {//Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
62                                 if(document.readyState=== "complete") {63 document.detachEvent("onreadystatechange", arguments.callee);64 init();65 }66 });//绑定回调到一定执行能load事件
67 window.attachEvent("onload", init);//如果是IE且非iframe情况下
68                     //持续的检查,看看文档是否已准备
69                     vartoplevel= false;70                     try{71 toplevel=window.frameElement== null;72 }catch(e) {}73 (function() {74                         if(document.documentElement.doScroll&&toplevel) {75                             if(isReady) {76                                 return;77 }78                             try{//If IE is used, use the trick by Diego Perini
79                                 //http://javascript.nwbox.com/IEContentLoaded/
80 document.documentElement.doScroll("left");81 }catch(e) {82 setTimeout(arguments.callee,1);83                                 return;84 }//执行在等待的函数
85 init();86 }87 })();88 }89 };90 window.ready= function(fn) {//绑定上监听事件
91 bindReady();//如果dom已经渲染
92                 if(isReady) {//立即执行
93 fn.call(document);//否则,保存到缓冲队列,等上面的监听事件触发时,再全部执行
94 }else if(readyList) {//将回调增加到队列中
95 readyList.push(fn);96 }97 };98 })(window);99     </script>
100     <scripttype="text/javascript">
101         varmiddle_x=3;102         //页面head中js执行完毕后,执行队列(页面尾部的js,定时器回调、事件回调,究竟哪个先执行,这个随机的);
103 setTimeout(function(){104 console.log("Timeout:"+(ax+before_x+middle_x+middle_y+bx+cx+domLoad_x+inner_x));105 },0);106         varinter=setInterval(function(){107 console.log("Interval:"+(ax+before_x+middle_x+middle_y+bx+inner_x+domLoad_x+cx));108 clearInterval(inter);109 },5000)110         varmiddle_y=1;111 window.onload= function(event){112 console.log("onloaded");113 }114 ready(function(event){115 console.log("dom loaded");116 });117     </script>
118     <scripttype="text/javascript"src="b.js"></script>
119 </head>
120 <body>
121      <inputtype="text"id="inp_click"onclick="inner_x =1;for(var i=0;i<1000000;i++){inner_x++};console.log('clickEvent:'+inner_x);">
122 </body>
123 </html>
124 <scripttype="text/javascript"src="c.js"></script>
125         <scripttype="text/javascript">
126             varstart_time= newDate().getTime();127             for(vari= 1;i<1000000;i++){128
129 }130             varend_time= newDate().getTime();131 console.log('after the html,wait:'+(end_time-start_time));132             varinp=document.getElementById("inp_click");133             varevent=document.createEvent("MouseEvent");134 event.initMouseEvent("click",true,true,document.defaultView,0,0,0,0,0,false,false,false,false,0,null);135 inp.dispatchEvent(event);136             vardomLoad_x= 4;137         </script>

此时浏览器显示结果为

或者为

本文首发:http://www.cnblogs.com/sprying/archive/2013/05/29/3105268.html参考:http://www.cnblogs.com/diguonianzhu/archive/2012/06/29/2570371.html

转载于:https://www.cnblogs.com/sprying/archive/2013/05/29/3105268.html

JavaScript的setTimeout与setInterval执行时机相关推荐

  1. JavaScript———从setTimeout与setInterval到AJAX异步

    setTimeout与setInterval执行 首先我们看一下以下代码打印结果 1 2 3 4 5 6 7 console.log(1); setTimeout(function() { conso ...

  2. 关于Javascript 中 setTimeout和setInterval的总结和思考

    1. JavaScript 单线程 我们通常说,javascript是单线程,指的是解释和执行js代码的引擎是单线程. 而对于浏览器来说,浏览器并不是单线程的,浏览器的线程通常包括:渲染引擎线程(负责 ...

  3. Javascript的setTimeOut()和setInterval()的定时器用法

    Javascript用来处理延时和定时任务的setTimeOut和setInterval函数应用非常广泛,它们都用来处理延时和定时任务,比如打开网页一段时间后弹出一个登录框,页面每隔一段时间发送异步请 ...

  4. JavaScript之setTimeout与setInterval的用法与区别

    }, 1000) } 那为啥使用let就可以了呢: 其实使用let之后,也没有改变执行机制,仍然是最后执行的alert(),但是let可以在每一次把更新的变量i传进函数体内,也就是每一次的i加1之后, ...

  5. 如何使用定时器settimeout、setInterval执行能传递参数的函数(转)

    来自: http://www.cnblogs.com/wkylin/archive/2012/09/07/2674911.html var userName="jack"; //根 ...

  6. JavaScript 中的 setTimeout 和 setInterval 方法

    有时您不希望函数立即运行.您希望它重新执行,甚至在特定时间间隔后重复运行.JavaScript 为我们提供了两种实现方法: setTimeout 和 setInterval.下面,我们将来理解这两个方 ...

  7. JavaScript时间事件:setTimeout和setInterval

    Programmers use timing events to delay the execution of certain code, or to repeat code at a specifi ...

  8. JavaScript教程-setTimeout,setInterval,

    调度:setTimeout 和 setInterval 有时我们并不想立即执行一个函数,而是等待特定一段时间之后再执行.这就是所谓的"计划调用(scheduling a call)" ...

  9. javascript requestAnimationFrame 解决 setTimeout、setInterval 时间不准的方法。

    javascript requestAnimationFrame 解决 setTimeout.setInterval 时间不准的方法. 取代 setInterval <!DOCTYPE html ...

  10. JavaScript定时调用函数(SetInterval与setTimeout)

    setTimeout和setInterval的语法相同.它们都有两个参数,一个是将要执行的代码字符串,还有一个是以毫秒为单位的时间间隔,当过了那个时间段之后就将执行那段代码. 不过这两个函数还是有区别 ...

最新文章

  1. 独家 | 攀登数据科学家和数据工程师之间的隔墙
  2. 机器学习中的范数规则化之(二)核范数与规则项参数选择
  3. Python中的驻留机制:小数据池和代码块
  4. 用JSON.parse(JSON.stringify(itemData))序列化反序列化实现‘深度复制’
  5. 方法练习3_打印指定次数的HelloWorld
  6. spring 之 property-placeholder 分析
  7. 服务器操作系统与安装步骤,服务器操作系统与安装步骤
  8. 复制一个空洞文件且忽略掉其空洞内容
  9. ubuntu 的使用(五)—— 桌面(desktop)
  10. 愚公移山第一章伪代码
  11. 如何用photoshop识别图片上文字的字体
  12. 物料科目组设置和分配-OVK5/SM30(V_TVKM)/VKOA
  13. oracle ora-3136,[转]ORA-3136(WARNING Inbound Connection Timed Out)分析
  14. 计算机表格常用根式,excel怎么建立常用根式_在excel中怎样开根号�9�3
  15. OSChina 周四乱弹 ——裤子穿反就被开除了?
  16. Ubuntu18.04使用RPLIDAR A2M12雷达出错的解决办法
  17. 一个网站SEO优化方案
  18. Redis 性能测试
  19. ubuntu nginx服务器安装SSL证书
  20. 前后端分离php验证码

热门文章

  1. MyBaties入门
  2. Silverlight中使用Timer的方法
  3. Vue动态组件异步组件
  4. 牛客网暑期ACM多校训练营(第四场)G Maximum Mode(思维)
  5. 关于web.xml配置中的url-pattern
  6. Orcle数据库 表的 内置函数 内链接 外连接 相关练习题
  7. mmo游戏开发应在profile下运行,才能保证正式运行不卡
  8. “SecureCRT遇到一个致命的错误且必须关闭”处理办法
  9. 【BZOJ 4503】4503: 两个串 (FFT)
  10. 将“早期版本的Windows”改名