setTimeout和setInterval区别(更新中)

来源:互联网 发布:淘宝3c证书编号在哪里 编辑:程序博客网 时间:2024/06/13 16:21
setTimeout(表达式,延时时间)在执行时,是在载入后延迟指定时间后,去执行一次表达式,记住,次数是一次

而setInterval(表达式,交互时间)则不一样,它从载入后,每隔指定的时间就执行一次表达式。

二者即为两个定时器。

window.setTimeout("function",time);//设置一个超时对象,只执行一次,无周期
window.setInterval("function",time);//设置一个超时对象,周期='交互时间'

停止定时:
window.clearTimeout(对象) 清除已设置的setTimeout对象
window.clearInterval(对象) 清除已设置的setInterval对象

javascript都是以单线程的方式运行于浏览器的javascript引擎中的, setTimeout和setInterval的作用只是把你要执行的代码在你设定的一个时间点插入js引擎维护的一个代码队列中, 插入代码队列并不意味着你的代码就会立马执行的

先谈谈setTimeout

function click() {// code block1...setTimeout(function() {// process ...}, 200);// code block2} 

假设我们给一个button的onclick事件绑定了此方法, 当我们按下按钮后, 肯定先执行block1的内容, 然后运行到setTimeout的地方, setTimeout会告诉浏览器说, "200ms后我会插一段要执行的代码给你的队列中", 浏览器当然答应了(注意插入代码并不意味着立马执行), setTimeout代码运行后, 紧跟其后的block2代码开始执行, 这里就开始说明问题了, 如果block2的代码执行时间超过200ms, 那结果会是如何? 或许按照你之前的理解, 会理所当然的认为200ms一到, 你的process代码会立马执行...事实是, 在block2执行过程中(执行了200ms后)process代码被插入代码队列, 但一直要等click方法执行结束, 才会执行process代码段, 从代码队列上看process代码是在click后面的, 再加上js以单线程方式执行, 所以应该不难理解. 如果是另一种情况, block2代码执行的时间<200ms, setTimeout在200ms后将process代码插入到代码队列, 而那时执行线程可能已经处于空闲状态了(idle), 那结果就是200ms后, process代码插入队列就立马执行了, 就让你感觉200ms后, 就执行了.

再看看setInterval
这里可能会存在两个问题:
1.时间间隔或许会跳过
2.时间间隔可能<定时调用的代码的执行时间

function click() {// code block1...setInterval(function() {// process ...}, 200);// code block2}

和上面一样我们假设通过一个click, 触发了setInterval以实现每隔一个时间段执行process代码

比如onclick要300ms执行完, block1代码执行完, 在5ms时执行setInterval, 以此为一个时间点, 在205ms时插入process代码, click代码顺利结束, process代码开始执行(相当于图中的timer code), 然而process代码也执行了一个比较长的时间, 超过了接下来一个插入时间点405ms, 这样代码队列后又插入了一份process代码, process继续执行着, 而且超过了605ms这个插入时间点, 下面问题来, 可能你还会认为代码队列后面又会继续插入一份process代码...真实的情况是,由于代码队列中已经有了一份未执行的process代码, 所以605ms这个插入时间点将会被"无情"的跳过, 因为js引擎只允许有一份未执行的process代码, 说到这里不知道您是不是会豁然开朗呢...

为了这种情况你可以用一种更好的代码形式

setTimeout(function(){//processingsetTimeout(arguments.callee, interval);}, interval); 

这样就不会产生时间点被跳过的问题内容就到这里




for(var i = 0; i < 10; i++) {    setTimeout(function() {        console.log(i);    }, 1000);}

1. 首先说说为什么最终输出的是10次10, 而不是你想象中的 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
   因为setTimeout是异步的!
   你可以想象由于setTimeout是异步的, 因此我们将这个for循环拆成2个部分
   第一个部分专门处理 i 值的变化, 第二个部分专门来做setTimeout
   因此我们可以得到如下代码
   // 第一个部分
   i++;
   ...
   i++; // 总共做10次

   // 第二个部分
   setTimeout(function() {
      console.log(i);
   }, 1000);
   ...
   setTimeout(function() {
      console.log(i);
   }, 1000); // 总共做10次

   这样一拆后, 我相信你肯定知道之前那个for循环的运行结果了.
   由于循环中的变量 i 一直在变, 最终会变成10, 而循环每每执行setTimeout时, 其中的方法还没有真正运行, 等真正到时间执行时, i 的值已经变成 10 了!
   i 变化的整个过程是瞬间完成的, 总之比你异步要快, 就算你setTimout是0毫秒也一样, 会先于你执行完成.

 for(var i = 0; i < 10; i++) {       setTimeout(function() {           console.log(i);       }, 0);   }


回调函数

1、回调函数就是那些自己写的,但是不是自己来调,而是给别人来掉的函数。(消息响应函数就可以看成是回调函数,因为是让系统在合适的时候去调用。这不过消息响应函数就是为了处理消息的,所以就拿出来单做一类了。其实本质上就是回调函数。)

2、回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。这一设计允许了底层代码调用在高层定义的子程序。回调的形式因程序设计语言的不同而不同。(C, C++ and Pascal允许将函数指针作为参数传递给其它函数。其它语言,例如JavaScript,Python,Perl和PHP,允许简单的将函数名作为参数传递。Objective-C中允许利用@selector关键字传递SEL类型的函数名。)

回调允许函数调用者在运行时调整原始函数的行为。因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。

0 0
原创粉丝点击