1 以下代码输出结果依次为1、3、20
<script> var num = 10; alert(1); num = 20; setTimeout("alert(num)",0); alert(3); </script>
2 以下代码输出3个3
for(var i=0; i<3; i++){
setTimeout(function (){
console.log(i);
}, 0)
}
JavaScript引擎是单线程运行的,浏览器无论在什么时候都只且只有一个线程在运行JavaScript程序.注意这里的浏览器模型定时计数器并不是由JavaScript引擎计数的,因为JavaScript引擎是单线程的,如果处于阻塞线程状态就计不了时,它必须依赖外部来计时并触发定时,所以队列中的定时事件也是异步事件。
同步任务(for循环、console等)
异步任务(回调函数以及ajax、setTimeout等)
于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程(call stack)任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
具体来说,异步运行机制如下:
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。这个过程会不断重复。
所谓"回调函数"(callback),就是那些会被主线程挂起来的代码,前面说的点击事件$(selectot).click(function)中的function就是一个回调函数。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。例如ajax的success,complete,error也都指定了各自的回调函数,这些函数就会加入“任务队列”中,等待执行。
定时器的返回值
定时器会返回一个数字值id,可以由clearInterval(id)或clearTimeout(id)来实现对对应定时器的清除。
setInterval()/setTimeout()BOM中的Window对象方法,以返回数字值id来清除定时器的排序位置存在一定的兼容性问题。通常采用一个变量接受定时器产生的返回值id,通过变量来这种方式来实现关闭定时器操作的兼容性。
以下代码中,控制台先输出0,大概过1000ms即1s后,输出定时器setTimeout()方法的返回值1:
var Timer = setTimeout(function(){ console.log(Timer); },1000); console.log(0);
实际上,除了前两个参数,setTimeout()方法还允许添加更多的参数,它们将被传入定时器中的函数中。以下代码中,控制台大概过1000ms即1s后,输出2:
setTimeout(function(a,b){ console.log(a+b); },1000,1,1);
一般来说,setTimeout返回的整数值是连续的,也就是说,第二个setTimeout方法返回的整数值比第一个的整数值大1:
//控制台输出1、2、3 var Timer1 = setTimeout(function(){ console.log(Timer1); },100); var Timer2 = setTimeout(function(){ console.log(Timer2); },100); var Timer3 = setTimeout(function(){ console.log(Timer3); },100);
setInterval的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次。
HTML5标准规定,setTimeout的最短时间间隔是4毫秒;setInterval的最短间隔时间是10毫秒,也就是说,小于10毫秒的时间间隔会被调整到10毫秒。
在h5的环境中,当我们跳转到其他页面,老页面的js环境会被自动销毁,定时器什么都被销毁掉了,因此我们不需要关心老页面中,还有哪些js代码可能还会执行,因为用的是不同的js执行环境。