谈谈我对js执行机制的认知

一.明确

在学习js执行机制之前,我们可以必须要明确js的一个特点:就是js的是单继承的。这一点是非常重要的,方便我们理解后续的知识。

二.js中的任务

因为js是单线程的,所以js的任务需要一个一个的顺序执行,但是有的任务的执行事件很长,那么它后面的任务也会等待前一个任务执行完毕才能执行,这就会极大的造成资源浪费(毕竟CPU一直在空闲,而后面的任务却不能执行)。于是,js的设计者就将js的任务分为了同步任务和异步任务。

同步任务是指在主线程上执行的任务,只有前一个任务执行完毕之后才会执行下一个任务

异步任务是指不进入主线程,而进入任务队列的任务,只有当主线程内部的任务执行完了,才会去执行任务队列的任务。那怎么知道主线程执行栈为空呢?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去任务队列检查是否有等待被调用的函数。

二.js的Event loop

因为js是单线程的,所以当有很多任务需要执行时,这是我们就需要考虑一下这多个任务的执行顺序了,而想要知道这多个任务的执行顺序,首先我们就需要了解js的Event loop了,js的Event loop执行过程如下:

(1)所有的同步任务都在主线程上执行,形成一个执行栈

(2)主线程之外还存在一个“异步队列”,只要异步任务有了运行结果,就在任务队列内放置一个事件。

(3)一旦执行栈内的所有同步任务执行完毕,系统就会读取“任务队列”,看看队列里面有哪些事件,那么对应的异步任务,于是结束等待状态,进入执行栈,开始执行

(4)主线程不断重复上面的三步

上面的这些语句是比较官方的,所以我们可以用下面的图和语句来解释js的执行过程,首先先来一张图

 

我们将这张图片用文字来描述:

(1)同步任务和异步任务会分别进入不同的场所,如果当前任务是同步任务,那么该任务会进入主线程执行栈,如果当前任务是异步任务,那么就会进入Event Tab并注册函数

(2)当指定的事情完成后,Event Tab会将这个函数移入Event Queue。

(3)当主线程内的任务执行完毕后,就会去Event Queue读取对应的函数,进入主进程栈,并执行。

(4)上述过程不断重复,就是我们常说的Event  Loop。

三、JS任务的详细分类

其实我们在前面已经讲过了,js中的任务分为同步任务和异步任务,但这只是广义上的区分,而我们对任务有更精细的定义,

  • 宏任务:包括script代码段,setTimeOut以及setInterval
  • 微任务:包括Promise和process.nextTick;

不同类型的任务会进入不同的Event Queue。

事件循环的顺序决定js代码的执行顺序。进入整体代码script(宏任务)后,会开始第一次循环,接着执行所有的微任务,然后再从宏任务开始,等到该任务队列执行完毕,在执行所有的微任务。如此循环下去。接下来上图帮助理解一下

关于上述的执行过程我翻了很多资料,最后得出一个最终的结论就是:只有宏任务队列中的所有任务都执行完之后才会执行微任务,而且同一微任务队列中,会优先执行process.nextTick,然后再执行Promise的then方法。这个地方一定要注意!!!

下面上一道题,大家可以猜一下最终的答案

console.log('');

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})

process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})

大家可以写一下这道题的答案(大家都是js大佬,相信一看就知道这道题的答案了),这道题的答案就是

1,7,6,8,9,11,2,4,10,3,12,5

同时来一张运行结果图。

各位同学如果还有不理解的地方可以留言探讨,或者我有什么写错的地方也希望各位童鞋提醒一下,希望本文能帮助到各位

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值