先来看看代码
console.log('a');
setTimeout(function(){
console.log('b');
},0);
console.log('c');
你肯定知道这个结果是acb
为什么呢?其实这个问题在StackOverflow已经有人回答的很好了点击查看,如果还有不明白的话可以看Philip Roberts这个小伙子的视频点击查看,我是在这两个地方学习的,讲的很不错!
因为javascript是单线程语言,单线程运行同时,它有一个单一的调用堆栈,它可以做一件事的时间,这就是一个单独的线程装置
好吧,简单来说就是,javascript是一个单线程语言,它一次只能做一件事情,它不能一边做着setTimeout另一边执行你下面的代码,也就是说,它不能执行完console.log('a');之后就开始给你setTimeout(callback,0);还同时给你执行下面的console.log('c');吧,因此,浏览器会把延迟操作推到回调任务队列
这里要说一个事件循环,它只做一件很简单的事情,就是查看堆栈,并查看任务队列,如果堆栈是空的,它需要回调队列上的第一件事,将它推送到可以有效运行它的栈.所以我们看到,setTimeout被浏览器推到回调队列,然后继续执行堆栈上需要执行的代码,检索到堆栈是空的,去回调队列上拿任务回来执行.所以结果就为acb
我随便画了一下,我觉得应该差不多
1.先执行console.log('a');
2.看到有延迟操作or回调函数,推到回调队列
3.继续向下执行console.log('c');
4.执行完console.log('c');之后下面没有任务(代码)了,把回调队列上的任务拉过来
5.再执行setTimeout
记住,事件循环,它必须等到堆栈清除,才能将回调队列推送到堆栈上继续运行
那么现在看一个情况
function foo(){
return foo();
}
foo();
这样做,你的堆栈会炸掉哈哈哈,浏览器会告诉你Maximum call stack size exceeded
就像它报错的形状一样,堆栈都放不下了,超过最大堆栈大小
那么再来看练习题中那个setTimeout的题目是不是就很好理解了?
for(var i=0;i<=3;i++){
setTimeout(function(){
console.log(i);
},0):
}
//4444
如果你问为什么是4444,你是不是忘了for循环里的i++,这时候你再来访问i,人家早就+到4了
欢迎纠正错误!!请赐教