BOM之定时器

JavaScript中的时间是经过定时器控制的,他们分别是window.setInterval和window.setTimeout,咱们固然能够省略window,直接使用方法名称调用。css

 

一       setTimeoutjson

  在等待指定的毫秒数后执行函数,语法以下:浏览器

  setTimeout(code/function, milliseconds, param1, param2, ...)函数

  方法接受2个或多个参数,第一个是一段JS代码或一个函数引用,第二个是须要等待的时间(以毫秒计),若是第一个参数是函数引用,而且须要传递参数,能够在后面依次传入。方法返回一个惟一id,表明该定时器,使用clearTimeout(id)能够清除定时器。测试

1 setTimeout(functon(){
2         console.log(new Date());
3     },3000);
4 console.log(new Date());
5 //当即显示一次当前时间,3秒后又将显示一次

  经测试发现:若是第一个参数是一段JS代码而非函数引用,该代码将当即被执行,而不会延时等待。动画

 

二     setIntervalspa

  等同于 setTimeout(),但持续重复执行该函数。语法以下:线程

  setInterval(code/function, milliseconds, param1, param2, ...)code

  使用方法和setTimeout()相同。对象

1 function timer(){
2     var d = new Date();
3     document.body.innerText = d;
4 }
5 setInterval(timer,1000);

  上面是一个简单的定时器示例。

  另外,setInterval方法有一个严重的缺陷,那就是不能确保执行时间的准确性。

在执行setInterval()时,假如咱们设置每1s执行一次函数,但函数执行一次须要花费2s。浏览器会每隔1s就向一个事件队列中添加一个事件(即执行一次函数),当第一次执行完毕(3s以后了),这时队列中已经有2个事件正在排队了,因而浏览器当即执行第二个事件(等待队列中的第一个)。这样明显和咱们本意每1s执行一次函数不符。因此在setInterval中,与其说第二个参数是延时时间,不如说是每一个事件执行的最大间隔时间更为准确。由于当事件执行时间大于设置的间隔时间时,两个任务执行之间是没有间隔时间的。

  有些书上表示,到了设置的时间点,若是上一次的函数还没执行完,那么本次事件将不会被添加到事件队列中去,此次事件将被跳过,直到将来设置的某一时间点,前面的任务已经完成,才向队列中添加下一个事件。但浏览器其实是按照第一种方式管理事件队列的,即到了时间无论前面的是否执行完毕,都插入一个进去,而后依次等待执行。(我用的Chrome  76.0.3869.100测试)

  setInterval主要应用在绘制动画效果上,鉴于它对时间的不许确性,要想得到完美的动画效果请使用CSS3的Animation实现。另外,若是确实须要使用,请务必把握好间隔时间的设置。下面是使用setInterval封装的一个运动函数:

 1 var timer;
 2 function startMove(obj,json,Fn){
 3     var key;
 4     clearInterval(timer);
 5     timer = setInterval(function(){
 6         for(var prop in json){//json是一个包含须要改变的属性和目标值的对象。  7             var bridge;
 8             if(prop == 'opacity'){
 9                 bridge = getStyle(obj,prop)*100;//为了便于计算,先放大100倍 10             }else{
11                 bridge = parseInt(getStyle(obj,prop));
12             }
13             var speed = (json[prop] - bridge)/6;
14             speed = speed > 0?Math.ceil(speed):Math.floor(speed);//这里为了得到更好的动画效果,动态设置了运动速度。你固然能够给一个常数做为运动速度 15             if(prop == 'opacity'){
16                 obj.style[prop] = (bridge + speed) / 100;
17             }else{
18                 obj.style[prop]= bridge + speed + 'px';
19             }
20             if(bridge != json[prop]){
21                 key = false;
22             }else{
23                 key = true;
24             }
25             if(key){
26                 clearInterval(timer);
27                 if(Fn)Fn();//当目标运动完成,执行回调函数 28             }
29         }
30     },30);
31 }
32     
33 function getStyle(obj,prop){//获取css样式值
34     if(obj.currentStyle){//IE 35         return obj.currentStyle(prop);
36     }else{//其余 37         return getComputedStyle(obj,false)[prop];
38     }
39 }

 

  网上不少文章亦或是不少出版书籍都把这两个方法和DOM放在一块儿或者单独讲解,我想他们这么作的缘由大概是这两个方法在JavaScript中主要应用在实现DOM元素的动画效果上。那么我为何要把他们放在BOM里面讲呢?

  咱们知道,JS的执行是单线程的,当代码运行到这两个方法时,理论上应该等待它绑定的代码执行完再日后执行其余代码,实际上他们并不会阻塞后面的代码,这又是为何呢?原来每当遇到延时程序时,浏览器都会为它单独开启一个线程,换言之,他们的时间是由浏览器操纵的,而不是JavaScript。另外一个明显的理由是这两个方法原本就是绑定在window对象上的,是由浏览器实现的,因此我把它放在BOM讲啦!

相关文章
相关标签/搜索