代码已经过测试。
知识点一:js的事件循环Event Loop
js是单线程执行的。js的执行机制把任务分为两类:同步任务、异步任务。
同步任务先执行,执行过程中遇到异步任务,就将其放入任务队列当中,继续执行同步任务。同步任务执行完之后,再去检查任务队列中要处理的异步任务。
具体的关于Event Loop的内容参考文章:并发模型与事件循环
知识点二: setTimeout
函数setTimeout接受两个参数:待加入队列的消息和一个延迟(可选,默认为 0)。这个延迟代表了消息被实际加入到队列的最小延迟时间。如果队列中没有其它消息,在这段延迟时间过去之后,消息会被马上处理。但是,如果有其它消息,setTimeout
消息必须等待其它消息处理完。因此第二个参数仅仅表示最少延迟时间,而非确切的等待时间。
接下来开始看具体题目
测试1:
// 先输出5
// 然后过3s,一次性输出5个5
// 先从上到下执行同步代码,碰到异步的代码会将其插入到任务队列当中等待
function test1(){
for(var i = 0; i < 5; i++){
setTimeout(function(){
console.log(i)
},3000) // 5个setTimeout任务都是等待3s执行,所以3秒一过,大家都输出。
}
console.log(i)
}
测试2:与1不同在for循环里有一个闭包,i每次是不同的、独立的。
// 先输出5
// 过3s,一次性输出0 1 2 3 4
// 先从上到下执行同步代码,碰到异步的代码会将其插入到任务队列当中等待
function test2(){
var j = 1;
for(var i = 0; i < 5;i ++){
(function(j){
setTimeout(function(){
console.log(j)
},3000) // 5个setTimeout任务都是等待3s执行,所以3秒一过,大家都输出。
})(i)
}
console.log('for同步代码执行之后' + i)
}
测试3:与2不同在延迟时间的设定。i*1000表示后进入队列任务比它前一任务延迟一秒执行。
// 先输出5
// 再按时间间隔为1s输出0 1 2 3 4
function test3(){
for(var i = 0; i < 5;i ++){
(function(){
setTimeout(function(){
console.log(i)
},i*1000) // 与2不同在执行时间间隔上面。后进入队列都比它前一任务延迟一秒执行。
})(i)
}
console.log('for同步代码执行之后' + i)
}
测试4:与3不同在,setTimeout的第一参数,因为是无返回值的闭包,所以第一参数变成了undefined,延时失效。因此会立即执行。
// 立即输出0 1 2 3 4 | 5
// 因为setTimeout的一个参数不是function类型,所以setTimeout失效
// 相当于一个for循环内一个单纯闭包
// 独立作用域
function test4(){
for(var i = 0; i < 5;i ++){
setTimeout( (function(){
console.log(i)
})(i), i*1000) // 与3不同在立即执行函数的位置是在setTimeout内部
}
console.log('for同步代码执行之后' + i)
}