借鉴一道题:
代码如下:
for(var i=0;i<5;i++){
setTimeout(function(){
console.info(new Date(),i);
},1000);
};
console.info(new Date(),i);
输出结果是什么?
可以看出先打印出了一个5,这是第六行代码的输出,然后间隔1s过后,同时打印出了5个5;即:5->5,5,5,5,5;
修改一
想要打印出5->1,2,3,4,5;的效果,如何修改代码呢?
之所以会连续打印出5个5,是因为循环体里的输出语句是在1s过后才会加入执行队列,这时“i”的值已经变成了5;为了打印出1,2,3,4,5;可以在每一次循环的时候立即执行一个函数,把当前的“i”当做参数传入进来,那么每次拿到的“i”就一样了;
function outer(n){
setTimeout(function(){
console.info(new Date(),n);
},1000);
};
for(var i=0;i<5;i++){
outer(i);
};
console.info(new Date(),i);
修改二
先执行循环体内的输出,再执行最外层的输出;即先隔秒输出0,1,2,3,4;然后再输出5;如何修改代码呢?
换种思路就是先执行异步操作,再执行同步代码;与js原本的执行顺序正好是相反的。当有明确的先后执行顺序时,可以利用promise来控制。
var tasks=[];
function task(n){
return new Promise(function(resolve,reject){
setTimeout(function(){console.info(new Date(),n);resolve();},n*1000)
});
};
for(var i=0;i<5;i++){
tasks.push(task(i));
};
Promise.all(tasks).then(function(){
setTimeout(function(){console.info(new Date(),i)},1000);
});
上面的面试题,只是提供了解决方法,而没有讲述javascript的运行原理,下面就是本文的重点: