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

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

时间:2023-04-02 15:43:55 HTML

好的程序员的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中没有异步,只能自上而下执行。如果上一行的解析时间很长,后面的代码就会被阻塞。对于用户来说,阻塞就意味着“卡住”,导致用户体验不佳。  所以,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  同步任务进入主线程后,会一直执行到主线程空闲,然后去eventqueue中检查是否有可执行的异步任务。如果有,它将被推入主进程。  那么在上面的例子中,你能描述一下它的执行顺序吗?console.log(1)是同步任务,放到主线程里面setTimeout()是异步任务,放到eventtable里面,0秒后执行push到eventqueueconsole.log(3是一个同步任务,放在主线程里面  当controlbar上打印出1和3的时候,主线程就去eventqueue(事件队列)中检查是否有可执行的函数,执行setTimeout中的函数。3.eventloop(2)  inJS那么,上面的eventloop就是我对JS执行机制的理解,直到我遇到了下面的代码  Example2:setTimeout(function(){console.log('Thetimer已经启动')});newPromise(function(resolve){console.log('现在执行for循环');for(vari=0;i<10000;i++){i==99&&resolve();}}).then(function(){console.log('Thenfunctionisexecuted')});console.log('Codeexecutionends');  试试看,上面我们刚学的JS执行机制来分析:setTimeout是一个异步任务,就是pleventtablenewPromise中的aced是同步任务,放在主进程中,直接执行打印console.log中的函数('现在执行for循环').then是异步任务,放在eventtableconsole.log('代码执行结束')。是同步代码,放入主进程直接执行  所以,结果是:立即执行for循环---代码执行结束---定时器启动---是然后功能执行?  亲自执行后,结果不是这样的,而是:立即执行for循环---代码执行完毕---执行then函数---定时器已经启动  所以,是不是异步任务的执行顺序,不是前后顺序,而是其他规定?其实按照异步和同步的划分,是不准确的。  准确的划分方法是:macro-task(宏任务):包括整体代码脚本,setTimeout,setIntervalmicro-task(微任务):Promise,process.nextTickJS引擎执行机制  按照这种分类方式,JS执行机制为:  执行一个宏任务,如果在执行过程中遇到微任务,则将其放入微任务的“事件队列”  当前宏任务执行完毕后,勾选“事件队列”Queue,依次执行所有的microtasks  重复以上2步,结合eventloop(1)eventloop(2),是一个更准确的JS执行机制  试试看刚学的执行机制,来分析例子2:  先执行脚本下的宏任务,遇到setTimeout就放入宏任务的“队列”  遇到newPromise直接执行,打印“现在执行for循环》  遇到then方法就是microtask,p把它放在微任务的“队列”中。  打印“代码执行完成”  本轮宏任务执行完毕,查看本轮微任务,在then方法中找到一个函数,打印“then函数执行完毕”  这里,这个round事件循环就全部完成了。  在下一个循环中,先执行一个宏任务,发现宏任务的“队列”中有setTimeout中的一个函数,执行并打印“定时器已启动”  于是最后的执行顺序就是:立即执行for循环---代码执行结束---执行then函数---定时器启动4、说说setTimeout  这段setTimeout代码是什么意思?我们一般说:3秒后,setTimeout会执行setTimeout(function(){console.log('executed')},3000)  但是这个说法并不严谨,准确的解释是:3秒后秒后,setTimeout中的函数会被推入eventqueue,eventqueue(事件队列)中的任务只会在主线程空闲时执行。