js定时器学习笔记

来源:互联网 发布:程序员怎样创业 编辑:程序博客网 时间:2024/05/21 16:58

做一下笔记。。。()(4.20修改更新)
参考的资料:
《JavaScript 高级程序设计》
http://www.w3school.com.cn/jsref/met_win_settimeout.asp,
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setTimeout,
http://stackoverflow.com/questions/4506074/settimeout-with-string-or-anonymous-function-reference-speedwise#userconsent#
http://www.cnblogs.com/chinahnzl/articles/612147.html
http://caibaojian.com/about-settimeout.html
http://www.cnblogs.com/dojo-lzz/p/4606448.html
http://ejohn.org/blog/how-javascript-timers-work/等。。。。
一、关于定时器:
setTimeout(func/code,time),setInterval(func/code,time),都有2个参数,前者是要执行的代码(调用的函数或者代码串),后者为需要等待的时间或者是code执行的时间间隔。
简单计时:

function timedMsg(){    var t=setTimeout("alert('5 seconds!')",5000)}

二、2者区别:setTimeout()是在time时间后执行一次代码,而setInterval是以time为时间间隔重复执行时间代码,直到清除这个定时器。
不过,setTimeout()也可以实现重复执行,也就是让code自身再次调用setTimeout。
例如:

function showTime(){    var date = new Date();    console.log("The time is:" + date.toString());    setTimeout(arguments.callee,2000);    //arguments.callee这里是获取对当前执行的函数的引用。    //也可以写成setTimeout("showTime()",2000);}showTime();

这和setInterval()的效果基本上一样,但是用setinterval有2个问题(参考《JavaScript 高级程序设计》):(1)某些间隔会被跳过,(2)多个定时器的代码执行之间的间隔可能会比预期的小。
(1)对于某些间隔会被跳过,是因为JavaScript引擎有这么个设定:当使用setinterval时,仅当任务队列中没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中(关于具体js运行机制,看下面)。那么当定时器的执行代码时间超过了循环时间时,可能会有多个定时器代码实例想加入到队列中,但由于上述原因,后面的代码实例加不了,这就造成了某些间隔会被跳过。不过这里有个问题:

对于不同浏览器,我发现关于间隔跳跃可能的结果是不同的,考虑到它们关于执行时间,2个定时器的优先级等不同设定问题,这里还需以后再给予验证。。。o(╯□╰)o

(2),对于间隔可能比预期的小很好理解。首先要注意的是:代码实例插入队列的时间并不是开始执行的时间。如果某个主线程中的任务非常耗时,超过了setinterval的时间间隔,并且setinterval的执行时间又小于循环时间,那么可能会有多个的setinterval代码在可运行前插入了队列中,这将导致,代码实例的运行间隔时间为其执行时间,而不是循环时间。例如:

setInterval(function(){     console.log(2);  },1000);   (function (){        sleeping(3000);  })();

结果就是等到第二行语句运行完成以后,立刻连续输出三个2,然后开始每隔1000毫秒,输出一个2。也就是说,setIntervel具有累积效应,如果某个操作特别耗时,超过了setInterval的时间间隔,排在后面的操作会被累积起来,然后在很短的时间内连续触发,这可能或造成性能问题.
所以,可能的话,尽量用setTimeout().

三、清除定时器:当setInterval()执行结束,会返回一个ID,可以根据它对定时器进行清除clearInterval。
例如:

var timer = setInterval(function(){    var date = new Date();    console.log("The time is:" + date.toString());},2000);function clear(){    clearInterval(timer);}

清除setTimeout也一样。

四、这里有几个注意点:
1.关于函数调用
对于无参函数,可以这么写: setTimeout(func,1000)或者setTimeout(”func()“,1000)
对于有参函数,可以这么写: setTimeout(“func(index)”,1000)。如果是使用了闭包传递对象那么可以 setTimeout(func(index),1000),其中func(index)返回一个无参函数。
在这里用”func()”实际上表示的是一个代码串,这是不推荐的方法,因为引擎内部使用eval(),将字符串转化为代码,而eval()实际上是不推荐使用的,因为:“它可以像拥有调用者的权力一样调用代码。如果你使用了字符串来运行eval(),那么你的代码可能被恶意方(不怀好意的人)影响, 通过在使用方的机器上使用恶意代码,可能让你失去在网页或者扩展程序上的权限。”
(来自https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval )

2.关于运行机制
首先,要知道js是单线程的。那么在这里执行定时器的时候,就是把相应函数在到达指定的时间间隔后将定时器代码添加到任务队列的尾部,注意,这里是插入,而不是执行。当当前的(主线程)执行栈任务执行完全,系统会去读取任务队列,执行函数。所以这里会等到主线程中所有的同步事件执行完,然后现有的任务队列中所有的事件都执行完,才会去执行定时器相应函数。(关于具体运行机制可以看《JavaScript高级程序设计》或者http://ejohn.org/blog/how-javascript-timers-work/)。

待续。。。

0 0