知识前置:
1.单线程(执行栈):在执行程序时,整体代码的执行由上而下,前面的执行完之后才能执行后面的。
详细解析: JavaScript 引擎是通过一种叫栈的数据结构来管理这些执行上下文。 在执行上下文创建好后,JavaScript 引擎会将执行上下文压入栈中,通常把这种用来管理执行上下文的栈称为执行上下文栈,又称调用栈
2.主线程:JS只有一个线程,这个线程负责解释和执行JS代码,称其为主线程,在这个主线程上,所有的代码按照顺序执行。
3.消息队列:消息队列里面放的是一些待触发执行的方法,如点击事件,当触发之后,会被通知主线程去执行
4.任务队列:同步代码放到执行栈中执行,异步代码会先存放到任务队列中,执行栈代码先执行,异步代码在执行栈执行完后再执行。任务队列优先级高于消息队列
5.同步:等待上一个事件执行完毕才执行下文,会阻塞,等待时间长,这种同步执行的操作容易使页面呈卡死状态,异步可以解决阻塞
6.异步(callback、Ajax、Promise、async await、nextTick()):不等前一个任务结束就执行。
详细解析:不进入主线程、而进入"任务队列"的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行
7.延迟函数执行(setTimeout、setInterval):等到执行栈清空的时候才会执行
8.事件轮询:先执行同步的的事件,监听执行栈,并确定执行栈是否为空。如果执行栈是空的(等同步的事件执行完),它就检查消息队列(异步的事件),消息队列的事件就会放入执行栈去执行,(简单来说执行栈有就执行,没有就不执行)
Js不存在异步,可以通过事件轮询实现异步,是单线程的。
JS的宿主环境(浏览器,node)存在异步,是多线程的。
优先级:同步>异步(任务队列>消息队列)>延迟函数
JavaScript中分为同步任务和异步任务,而异步任务中又分为宏任务和微任务两种,同一层级下,微任务永远比宏任务先执行
9.微任务(Promise、async/await、process.nextTick):执行完当前主线程任务后就要马上执行的任务
10.宏任务(setTimeout、setInterval、Ajax、事件绑定):可以理解是每次执行栈执行的代码就是一个宏任务
做题技巧
1.new Promise是一个构造函数,是同步任务
2.Promise.resolve().then 是微任务
3.async是同步任务
4.await方法返回的是一个Promise对象,后面相当于Promise then, 是微任务
5.定时器,加入下一次宏任务,是宏任务
简单题:
1.
console.log('aaaa');
setTimeout(()=>{
console.log('cccc');
}, 0);
console.log('bbbb');
解析:先同步后异步(setTimeout)
答案: aaaa bbbb cccc
2.
console.log('aaa');
setTimeout(() => console.log(111), 10);
setTimeout(() => console.log(222), 0);
console.log('bbb');
解析:先同步后异步,延迟异步(setTimeout)
答案: aaa bbb 222 111
3.
console.log('aaa');
(async ()=>{
console.log(111); //在async里面
})().then(()=>{
console.log(222); //在async的then里面
});
console.log('bbb');
解析:先同步后异步,异步分宏任务、微任务,同级先微后宏
(async是同步任务,Promise.resolve().then是异步微任务)
答案: aaa 111 bbb 222
4.
console.log('aaa');
(async ()=>{
console.log(111);
await console.log(222);
console.log(333);
})().then(()=>{
console.log(444);
});
console.log('ddd');
解析:先同步后异步,异步分宏任务、微任务,同级先微后宏
(async是同步任务,await 的console.log是同步的,所以会立即执行,await
本身就是then
,所以console.log(333)
无法直接执行)
答案: aaa 111 222 ddd 333 444
5.
console.log('aaa');
setTimeout(()=>console.log('t1'), 0);
(async ()=>{
console.log(111);
await console.log(222);
console.log(333);
setTimeout(()=>console.log('t2'), 0)
})().then(()=>{
console.log(444);
})
console.log('bbb');
答案: aaa 111 222 bbb 333 444 t1 t2
面试题:
1.滴滴智能中台
setTimeout(function(){
console.log('1')
});
new Promise(function(resolve){
console.log('2')
for (var i = 0; i < 10000; i++){
i == 99 && resolve()
}}).then(function(){
console.log('3')}
)
console.log('4');
答案:2 4 3 1
2.小米前端实习面经
//执行顺序
async function async1() {
console.log('async1 start')
await async2();
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1();
new Promise(
function (resolve) {
console.log('promise1')
resolve();
})
.then(
function () {
console.log('promise2')
})
console.log('script end')
答案:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout