下面这段代码输出结果是? 为什么?
var a = 1;
setTimeout(function(){
a = 2;
console.log(a);
}, 0);
var a ;
console.log(a);
a = 3;
console.log(a);
- 先输出1,再输出3,最后输出2
解释
- 初始化运行时,主线程会去执行所有的同步任务,而将setTimeout挂起,等到同步任务结束,输出1和3后,再运行setTimeot内部的匿名函数,输出2
下面这段代码输出结果是? 为什么?
var flag = true;
setTimeout(function(){
flag = false;
},0)
while(flag){}
console.log(flag);
- 结果就是什么也不输出
原因
- 因为这是同步任务,程序由上到下执行,遇到while()死循环,导致任务队列中的setTimeout函数占用不到主线程,无法更改flag值,while结束不了,自然也输出不了值.
实现一个节流函数。
var timer
function fruquency(){
if(timer){clearTimeout(timer)}
timer = setTimeout(function(){console.log('do something')},2000)
}
简单解释单线程、任务队列的概念。
- 单线程模型指的是,JavaScript 只在一个线程上运行。也就是说,JavaScript 同时只能执行一个任务,其他任务都必须在后面排队等待。
- 好处是实现起来比较简单,执行环境相对单纯;
- 坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行
- 任务队列
JavaScript 运行时,除了一个正在运行的主线程,引擎还提供一个任务队列(task queue),里面是各种需要当前程序处理的异步任务。
首先,主线程会去执行所有的同步任务。等到同步任务全部执行完,就会去看任务队列里面的异步任务。如果满足条件,那么异步任务就重新进入主线程开始执行,这时它就变成同步任务了。等到执行完,下一个异步任务再进入主线程开始执行。一旦任务队列清空,程序就结束执行。
- 事件循环
JavaScript 引擎怎么知道异步任务有没有结果,能不能进入主线程呢?答案就是引擎在不停地检查,一遍又一遍,只要同步任务执行完了,引擎就会去检查那些挂起来的异步任务,是不是可以进入主线程了。这种循环检查的机制,就叫做事件循环(Event Loop)。