当前位置: 首页 > Web前端 > HTML5

好的web前端程序员分享JS引擎的执行机制

时间:2023-04-05 17:04:39 HTML5

好的web前端程序员分享JS引擎的执行机制,请先记住两点!JS是一种单线程语言。  JS的EventLoop就是JS的执行机制。深刻理解了JS的执行,就相当于深刻理解了JS中的eventloop。  1。三个灵魂问题:为什么JS是单线程的?为什么需要异步?单线程是如何实现异步的?  技术的出现与现实世界中的应用场景密切相关。同样,我们将结合现实场景来回答这三个问题。  (1)为什么JS是单线程的?  JS本来就是为在浏览器中使用而设计的,所以想象一下如果浏览器中的JS是多线程的。  场景描述:  现在有两个进程,process1process2,因为是多进程JS,所以同时操作同一个dom。Process1删除dom,process2编辑dom,同时发出两条相互矛盾的命令。浏览器应该如何执行呢?  这样一想,应该就很容易理解为什么JS要设计成单线程了。  (2)为什么JS要异步?  场景描述:  如果JS中没有异步,只能自上而下执行。如果上一行的解析时间很长,后面的代码就会被执行block。对于用户来说,阻塞就意味着“卡住”,导致用户体验不佳。  所以,JS中存在异步执行。  (3)JS单线程是如何实现异步的?  既然JS是单线程的,只能在一个线程上执行,那么它是如何实现异步的呢?  是传递的事件循环(eventloop),了解eventloop机制,了解JS的执行机制。  2。Eventloop(1)  JS中的例子1,观察其执行顺序  console.log(1)setTimeout(function(){console.log(2)},0)console。log(3)  的运行结果为:132  也就是说setTimeout中的函数并不是立即执行,而是延迟一段时间,在满足一定条件后执行。这种代码称为异步代码。  所以,这里我们先知道JS中的一种分类方法,就是把任务分为:同步任务和异步任务。  按照这种分类方式:JS的执行机制是:  首先判断JS是同步还是异步,同步的会进入主进程,异步的会进入eventtable  异步任务在事件表中注册函数。当满足触发条件时,将其推入事件队列  。同步任务进入主线程继续执行,直到主线程空闲,然后去eventqueue中检查是否有可执行的异步任务。如果有,则推入主进程  ,循环执行以上三步。这是事件循环。  那么在上面的例子中,你能描述一下它的执行顺序吗?  console.log(1)为同步任务,放入主线程  setTimeout()为异步任务,放入eventtable,0秒后推入eventqueue  console.log(3是同步任务,放在主线程里面  controlbar中打印1和3的时候,主线程去eventqueue(事件队列)检查是否有可执行函数,执行setTimeout中的函数  3、JS中的eventloop(2)  所以,上面的eventloop是我对JS执行机制的理解,直到遇到下面这段代码。  示例2:  setTimeout(function(){console.log('定时器已启动')});  newPromise(function(resolve){console.log('立即执行for循环啦');  for(vari=0;i<10000;i++){i==99&&resolve();  }}).then(function(){console.log('executethenfunction')});console.log('代码执行结束');  尝试按照我们上面刚学的JS执行机制来分析:  setTimeout是异步任务,放在eventtable  newPromise是同步任务,放在主进程,并直接执行并打印console.log('for循环即将执行')  .then是一个异步任务,放在eventtable  console.log('代码执行结束')是一段同步代码,放入主进程直接执行  所以,结果是:for循环立即执行---代码执行完成---定时器启动---执行函数是吗?  亲自执行后,结果不是这样的,而是:立即执行for循环---代码执行结束---执行then函数---定时器启动  那么,是不是异步任务的执行顺序,不是前后台的顺序,而是其他的规定呢?其实按照异步和同步的划分,是不准确的。  准确的划分方法是:  macro-task(宏任务):包括整体代码脚本,setTimeout,setInterval  micro-task(微任务):Promise,process.nextTick  follow这个JS的执行机制是:  执行一个宏任务,如果过程中遇到微任务,会被放入微任务的“事件队列”中  当前宏任务执行完毕后,它会检查微任务的“事件队列”,并依次执行所有微任务。  重复上面2步,结合eventloop(1)eventloop(2),是比较准确的JS执行机制  尝试按照刚刚学习的执行机制,分析例子2:  先执行脚本下的宏任务,遇到setTimeout就放到宏任务的“队列”中  遇到newPromise就直接执行,打印“立即执行for循环”  遇到then方法,就是一个microtask,放入microtask的“queue”中  print"codeexecutioncompleted"  本轮macrotask执行完毕,查看本轮microtask,在then方法中找到一个函数,print"thenfunctionisexecuted"  这里,这一轮eventloop全部搞定了。  在下一个循环中,先执行一个宏任务,发现在setTimeout的“队列”中有一个函数宏任务,执行并打印“定时器已启动”  所以最终的执行顺序是:立即执行for循环---代码执行结束---执行then函数---定时器启动  4。这个setTimeout代码是什么意思?我们一般说:3秒后,setTimeout中的函数会被执行  setTimeout(function(){console.log('executed')},3000)  但是这个并不严谨,准确的解释是:3秒后,setTimeouteventqueue中的函数会被push到eventqueue中,eventqueue(事件队列)中的任务只会在主线程空闲时执行。  因此只有当(1)3秒后(2)主线程空闲且两者都满足时,函数才会在3秒后执行。10秒,那么这个函数只能在10秒后执行。