二三面_运行机制类
Posted 煜成'Studio
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二三面_运行机制类相关的知识,希望对你有一定的参考价值。
二三面_运行机制类
第一题
console.log(1);
setTimeout(function () {
console.log(3);
}, 0);
console.log(2);
问你最后的打印顺序是什么?
1 2 3
要知道两个概念
js是单线程的(大白话是:同一时间只能做一件事)
任务队列(异步操作看起来和单线程是冲突的,那怎么做到的那,其实就是任务队列):
1.同步任务:在js同步运行过程中的语句叫做同步任务,比如console.log
2.异步任务:setTimeout就是一个异步任务
解释第一道题:
js是从上到下运行,先console.log(1);,然后setTimeout是异步任务,要挂起,先不执行,js代码继续往后执行,执行同步任务console.log(2);,同步任务执行完毕,这个时候才会去处理异步任务,记住单线程任务队列是有一个优先顺序的,在js的运行机制的执行过程中,优先同步任务,同步任务处理完之后,才会去响应异步任务。
注意:上面的setTimeout里面的时间0其实不是0,规定浏览器这个事件最小是4ms,所以虽然是这么写成0或者小于4ms,都是按4ms算
第二题
console.log('A');
while (true) {
};
console.log('B');
输出什么?
‘A’
console.log(‘A’);是个同步任务,while不断循环,console.log(‘B’);不会被执行,while这个同步任务没有执行完根本不会执行到console.log(‘B’);
(window可以在任务管理器中强行关闭一直循环的进程,不然会卡住,ctrl+alt+delete)
console.log('A');
setTimeout(function () {
console.log('B');
}, 0);
while (true) {
};
输出什么?
‘A’
第三题
for(var i = 0; i < 4; i++) {
setTimeout(function () {
console.log(i);
}, 0)
}
问console.log会输出几次,每次的结果是什么?
4 4 4 4
解释:第一题讲的是同步任务和异步任务的优先关系,这个题讲的是异步任务的放入时间和执行时间。代码执行到异步任务的时候,就会把它放到异步队列吗?不是,浏览器有一个timer模块,主要是处理setTimeout和setInterval的,是一个定时器,到那个时间才会把这个语句放在异步队列中,for循环在执行的过程中,遇到setTimeout,定时器会记住这个语句,但是并没有去执行,i就加一了,for循环体在执行过程中,并没有真正地放到异步队列中去,for循环执行一次后,会执行异步队列,因为没到定时器的时间,所以异步队列中是没有setTimeout的,四个循环非常快的就执行完了,此时异步队列里没有东西,当时间到了,定时器会把setTimeout函数体扔到异步队列中,异步队列再等待一个叫事件循环Event Loop的东西再执行。
Event Loop
右边的是运行栈,执行同步任务的,上面的题目console.log(1)和console.log(3)都是同步任务,是放在运行栈里的,js引擎遇到setTimeout的时候会认为这是一个异步任务,不会把它让在运行栈中,会由浏览器的Timer模块把setTimeout拿走,拿走之后到setTimeout里面写的时间之后,Timer再把setTimeout函数体放到任务队列中,js引擎发现运行栈中没有同步任务了,就是运行栈已经空了,就去执行异步队列,发现里面有东西,读出来放到运行栈中去执行,这个时候setTimeout里面的函数体就变成了运行栈里面的同步任务,再去执行,执行完以后,这个栈又空了,空了再去监听这个异步队列中有没有,如果有继续像刚刚说的那样执行,如此循环,这个循环的过程就叫Event Loop。
三个要点:执行栈执行的是同步任务;什么时候去异步队列中去取任务;什么时候向异步队列中放异步任务;
什么时候会开启异步任务?三类
1.setTimeout、setInterval
2.DOM事件(执行DOM事件的时候需要addEventListener注册一个类型的事件,浏览器中会有一个单元的模块去接收这个东西,这个事件被触发的时候,也就是监听GUI线程接收到比如某个用户点了某个按钮或某个键盘,这个时候要触发一个事件,浏览器的那个模块就会把我们注册的函数体扔到异步队列中,如果浏览器的执行栈中是空的,就去异步队列中拿到这个函数体去执行,也就是我们注册事件的时候的响应函数,大家有时候说,我某个任务js一直在执行,我点按钮卡住了,就是因为这个原因,浏览器是单线程的,它有同步任务在执行那,你点任何按钮它也不会读异步任务队列,所以它根本就不会执行,让你看到的就是浏览器死掉了卡住了,这就是那个背后的原理)
3.ES6中的Promise
总之,在面试题中遇到这三种问题的时候,你一定注意了,这块考的是JS运行机制,你不要按照常规的方式去写。
总结:
理解JS的单线程的概念;
理解任务队列;
理解Event Loop;
理解哪些语句会放入异步任务队列;
理解语句放入异步任务队列的时机;
以上是关于二三面_运行机制类的主要内容,如果未能解决你的问题,请参考以下文章