继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

一起扫荡JavaScript(七)—— 聊聊JS运行机制

dorseyCh
关注TA
已关注
手记 50
粉丝 1.3万
获赞 1519

    JavaScript的运行机制一直是绕不开的话题,众所周知,JavaScript是单线程 + 异步队列的模式运行的,如何看待这种执行机制呢?同步异步,任务队列,又是怎样分配好这之中的先与后?

    为什么要单进程?

    JavaScript是运行再浏览器中的,DOM对象是JavaScript一个很重要的组成部分,直接或间接操作DOM也是JavaScript做得最多的那些事,当然node服务端或者dena开发者的除外。

    既然运行环境是在浏览器,操作DOM,假如说JavaScript是多线程的,如果线程A删除了某个DOM,线程B又要编辑这个DOM,这是两个矛盾的过程,请问浏览器要听谁的?

    既然单线程已成了必然,但是单线程不会执行很慢吗?因为各种各样的阻塞。这就是JavaScript面临的第二个问题。而JavaScript也有了一个很独特但很cool的解决方式:

    异步队列

    JavaScript在执行的过程中:

    会先判断执行的JS代码段(是的,JavaScript是一段一段执行的而非一行行执行)是同步还是异步,同步就进入主进程,异步就进入event table(你可以认为是大门签到处)

    异步任务在event table中注册函数,当满足触发条件后,被推入event queue(队列)

    同步任务进入主线程后一直执行,直到主线程空闲时(通常同步代码很快就执行完),才会去event queue中查看是否有可执行的异步任务,如果有就推入主进程中。

    JavaScript会不断的循环这个过程,即event loop。

    我们可以先来看一下这段代码:

console.log('同步1');
setTimeout(() => console.log('异步1'),0);
console.log('同步2');

    你会发现输出结果是:同步1 同步2 异步1,尽管异步1写在同步2的代码之前,而JavaScript实际上的执行是这样的:

https://img4.mukewang.com/5c77d4c60001d64d12490645.jpg

    看看下面稍微复杂点的题:

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');

    而最终的执行结果是:

    https://img1.mukewang.com/5c77d6400001ec6c04180300.jpg

    其实明白微任务与宏任务之间在队列中执行的优先级,这个过程中同步的先执行同步任务:

    console.log('script start');

    接下来执行到:

    async1();

    async1()内部先直接执行

console.log('async1 start');

    输出后,执行async2,async2内部执行这一条。

  console.log('async2');

    继续往下执行同步任务。
    遇到 new promise,先输出

  console.log('promise1');

    遇到承诺resolve,需要后续的捕获。这部分扔进队列中。

    同步继续进行到。

 console.log('script end');

    再回过头来执行异步队列中的任务。

    此时的异步队列中有什么任务呢?

    有宏任务setTimeout,微任务promise,跟await,setTimeout是宏任务放最后,依次输出:

    console.log('promise2');
  console.log('async1 end');

    再最后输出宏任务setTimeout中的任务

console.log('setTimeout');

    对于JavaScript的执行机制就暂时介绍到这啦。










打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP

热门评论

//输出结果有误,应为:
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout


查看全部评论