彻底理解JavaScript中的执行机制,不再恐惧代码输出结果

在这里插入图片描述

请写出以下代码的输出结果,这是一道笔试中非常常见的题目,就问你熟不熟悉,眼不眼熟,但是很多同学往往摔在这道题里,那我们就很有必要展开讲讲了,只有研究它,才能战胜它,所谓知己知彼百战百胜嘛。只要搞清楚其中的规则,万变不离其宗!题目再怎么变,你都能写出答案来。

首先这类题目常见的会包含同步任务、异步任务,异步任务又有宏任务和微任务,宏任务又有setTimeout、setInterval、script(整体代码)、UI交互等,而微任务包括Promise.then、process.nextTick等,将这些不同类型的任务放到一起,就容易混淆我们的判断。

首先我们要知道JavaScript是一门单线程语言,也就是说它不会同时处理多个任务,它只能一个一个地处理,就好比你去食堂打菜,食堂只有一个打菜的窗口和一个打菜的阿姨,那你就得排队,排到你了阿姨就给你打,你总不能自己抢上去打吧,那如果这样的话,一个个地等,如果一个任务耗时很长的话,那岂不是后面的都要等着,那像我们的网站,总不能因为一张图片太大加载不出来,就整个网站都在那空着吧,所以有了同步任务异步任务来解决类似的问题,当我们打开网站时,网页的渲染过程就是一大堆同步任务,像页面的结构,而像加载图片音乐之类占用资源大耗时久的任务,就是异步任务。我们来看一个任务执行的顺序图:

在这里插入图片描述
上图要表达的内容用文字来表述的话:

  • 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
  • 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
  • 主线程内的任务执行完毕为空(js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数),会去Event Queue读取对应的函数,进入主线程执行。
  • 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

来看一个简单的例子:

const promise = new Promise((resolve,reject)=>{
	console.log(1)
	console.log(2)
	resolve()
})
promise.then(()=>{
	console.log(3)
})
console.log(4)

//代码从上到下看,只有promise.then是异步任务,所以先把同步任务执行完之后,就会执行异步任务
//打印出来就是 1 2 4 3

但是面试题往往不会这么简单,往往都是像文中最开始放的那道题那样,多个任务,同步异步,宏任务微任务放在一起,那怎么办呢,不要慌,我们先来理解一下事件循环,还有微任务和宏任务的执行顺序,先看一下他们的关系图
在这里插入图片描述
我们在开篇的时候说到,整体的代码script就是一个宏任务,所以我们一开始是从一个宏任务开始第一次循环,遇到宏任务里面的微任务就先执行微任务,宏任务放到宏任务的队列,执行完所有的微任务之后,再继续执行下一个宏任务,一直循环到所有任务执行完毕,这就是事件循环

我们结合题目来具体分析一下

setTimeout(function(){
	console.log(1)
},100)
new Promise(function(resolve){
	console.log(2)
	resolve()
	console.log(3)
}).then(function(){
	console.log(4)
	new Promise((resolve,reject)=>{
		console.log(5)
		setTimeout(()=>{
			console.log(6)
		},10)
	})
})
console.log(7)
console.log(8)

我们同样从上往下边看边分析:
1.执行整个script代码,也就是第一个宏任务,首先是setTimeout,属于异步宏任务,我们把它先挂到宏任务的队列
2.接下来是new Promise,首先执行里面的同步代码,打印出2,遇到resolve,加入微任务的队列
3.执行后面的同步代码,打印出3
4.接着执行script中的同步代码,打印出7和8
5.第一个宏任务执行完毕,此时先解决微任务队列里面的微任务,也就是resolve
6.打印出4,遇到new Promise,按顺序打印出5,遇到定时器,将其加入宏任务队列,此时宏任务队列有两个定时器
7.但是需要注意的是第一个定时器的时间是100ms,第二个定时器的时间是10ms,所以先执行第二个定时器,打印出6
8.此时微任务队列为空,继续执行宏任务队列,打印出1
9.所以,这道题的答案是2 3 7 8 4 5 6 1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值