js引擎是单线程引擎,一段时间只能执行一个事件,为了控制要执行的代码,js拥有任务队列。队列中任务按照一定的顺序排列,而这些任务按照排列的顺序执行。
当函数foo1()箱与函数foo2()调用时一般先执行foo1()再执行foo2(),事件执行顺序与程序排列顺序相同叫“同步模式””
但是“同步模式”有时会出现缺点,如:
假设某函数foo()非常耗时,那么在执行foo()时用户可能误以为浏览器没响应,这时就应该让耗时较长的事件后执行避免浏览器无响应。
当事件执行顺序与程序排列顺序不同时,为“异步模式“”
利用setTimeout就完成异步,下面介绍setTimeout
setTimout()接受两个参数,第一个参数可以是字符串,也可以是函数,为指定的要执行的代码。
第二个参数是时间,单位毫秒,表示等待时间,它告诉js再过多长时间把当前任务添加到队列中,因此经过改时间后指定的代码未必执行。
当使用setTimOut时,当前任务会被添加到队列尾部,因此,当队列为空的时添加的代码会立即执行,当队列不为空时,要等待前面的代码执行完成以后再执行
for( var i = 1; i<=10; ++i){
setTimeout( function(){
console.log(i)},0)
}
这里输出10个11,这里输出10个值是因为循环了10次通过setTimeout( )将10个console.log(i)放在了队尾(上面说的,setTimeout会等待指定的时间后将添加的代码添加到队尾)
,但为什么会输出10个相同的值呢,为什么不是输出1,2,3,4,5,。。。10呢。这是因为虽然循环中的函数是在各个迭代中分别定义的,但是它们都是在一个共享的全局作用域上,因此实际上只有一个i。所以最后输出的i值是相同的,当循环结束时i为11,因此输出的都为11.
上面的10 11上面还有个数值46,这是调用setTimeout()后从返回的唯一数值ID
我们也可以建立新的作用域使得输出是1,2.。。10,如下
for( var i=1; i<=10; ++i ){
(function(){
var j = i
setTimeout( function(){console.log(j)},0 )
})()
}
以上代码可参考 《你不知道的js上册》
下面介绍setInterval(), setInterval()拥有两个参数,一个是字符串或函数,另一个是时间,表示每隔指定的时间调用一次指定的代码,
setInterval()也会返回一个唯一的数值ID,setTimeut和setInterval()都可以利用唯一数值ID取消还没执行的调用
setInterval()的间歇调用会一直执行,直到页面被卸载或者被取消
var num=0
function foo(){
num++
if( num==10 ){
clearInterval( intervalId )
console.log("结束了"+intervalId)
}
}
intervalId = setInterval( foo, 1000 )
这个函数在游戏里可以用到,因为游戏就是一帧一帧的图像,每隔 n 毫秒更新一次图像就成了游戏,动画。。。
上面的模式在也可以用setTimeout()来实现
var num = 0
function foo(){
num++
if( num<10 ){
setTimeout( foo,1000 )
}
else{
console.log("结束了")
}
}
foo()
js高级教程里说,后一个间歇调用可能在前一个间歇调用结束之前启动。我对这句话还不是很理解,但我觉得启动不是执行,js不可能同时执行两个任务因为js引擎是单线程的。js高后面高级定时器对这个有说明,马上看。顺便说下,定时器不是线程!!!
参考:http://www.ruanyifeng.com/blog/2012/12/asynchronous_javascript.html
js高级教程
你不知道的js上册