前端进阶系列(八):JS执行机制

递归季风
• 阅读 1717

一直以来,对JS的执行机制都是模棱两可,知道今天看了文章—《这一次,彻底弄懂JavaScript执行机制》《Event Loop的规范和实现》,才对JS的执行机制有了深入的理解,下面是我的学习总结。

2个要点

  • JS是单线程语言
  • Event Loop是JS的执行机制,为了实现主线程的不阻塞,Event Loop就这么诞生了。

2个概念(结合Browser环境和Node环境)

  • task queue(宏任务队列):setTimeoutsetIntervalsetImmediateI/OUI交互事件
  • microtask queue(微任务队列):Promiseprocess.nextTickMutaionObserver

看下图:

前端进阶系列(八):JS执行机制

  • queue可以看成一种数据结构,用以存储需要执行的函数
  • setTimeout等API注册的函数,会进入task队列
  • Promise等API注册的函数会进入microtask队列
  • Event Loop执行一次,从task队列中拉出一个task执行
  • Event Loop继续检查microtask队列是否为空,依次执行直至清空队列

情景再现

JS的执行逻辑,就好比只有一个窗口的银行,客户需要一个一个排队办理业务,假如现在排队的有两个人,第一个人是办理银行卡的,第二个人是取钱的,下面来个情景对话(这就类似上图的event loop):
客服:请问您办理什么业务?
客户1:办理银行卡。
客服:请先填写一份申请表。下一位!(此时客户1进入callback queue)
客服:请问您办理什么业务?
客户2:取钱
…………
(此时客户1已经完成申请表填写,但客户2还未结束,那么客户1还需等待,直到窗口前的这个客户办理结束)
客户1:我填好了,给您……

实例练习1

console.log(1)

setTimeout(() => {
    console.log(2)
    new Promise(resolve => {
        console.log(4)
        resolve()
    }).then(() => {
        console.log(5)
    })
})

new Promise(resolve => {
    console.log(7)
    resolve()
}).then(() => {
    console.log(8)
})

setTimeout(() => {
    console.log(9)
    new Promise(resolve => {
        console.log(11)
        resolve()
    }).then(() => {
        console.log(12)
    })
})

分解动作:

  1. 主进程运行的代码首先输出1、7;
  2. 再执行一次microtask输出8;
  3. 执行了一次task输出2,4;
  4. 再执行一次microtask输出5;
  5. 再执行另一个task输出9、11;
  6. 再执行一次microtask输出12

最终结果:
1、7、8、2、4、5、9、11、12

注意的:在Node环境下process.nextTick注册的函数优先级高于Promise,大家可以在Node环境下尝试下面的例子:

new Promise(resolve => {
    console.log(1)
    resolve()
}).then(() => {
    console.log(2)
})
new Promise(resolve => {
    console.log(3)
    resolve()
}).then(() => {
    console.log(4)
})
process.nextTick(() => {
    console.log(5)
})

console.log(6)

执行结果:1、3、6、5、2、4

实例练习2

setTimeout(() => {
    console.log(2)
}, 2)

setTimeout(() => {
    console.log(1)
}, 1)

setTimeout(() => {
    console.log(0)
}, 0)

有人说结果应该是0,1,2
但正确结果是2,1,0。
因为setTimeout最低延迟是4ms,值得注意。

我的博客:http://blog.rnode.me

参考文章:

原文:Event Loop的规范和实现
地址:https://juejin.im/post/5a6155126fb9a01cb64edb45
原文:这一次,彻底弄懂 JavaScript 执行机制
地址:https://juejin.im/post/59e85eebf265da430d571f89
原文:JavaScript 运行机制详解:再谈Event Loop
地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html
点赞
收藏
评论区
推荐文章
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Souleigh ✨ Souleigh ✨
4年前
前端 - 常见的异常捕获方法
前端异常捕获在ES3之前js代码执行的过程中,一旦出现错误,整个js代码都会停止执行,这样就显的代码非常的不健壮。从ES3开始,js也提供了类似的异常处理机制,从而让js代码变的更健壮,程序执行的过程中出现了异常,也可以让程序具有了一部分的异常恢复能力。js异常的特点是,出现不会导致JS引擎崩溃,最多只会终止当前执行的任务。回归正题,我们该如何在程序异常发生
郜小超 郜小超
5年前
浅谈promise和js执行机制(一)
作为一个入门级前端,今天是一个非常值得纪念的日子,因为这是我第一次在论坛上发表帖子,作为起步。虽然我觉得自己水平还是十分的有限,对一些细节的理解还不是很透彻,但是还是要迈出这一步,不管是给别的新手作为学习参考,还是自己以后回顾,总觉得需要把自己的成长记录下来,希望自己以后还是要多坚持,如果有不对的地方还是希望大家及时提出来,共同进步今天有时间翻到了
Symbol卢 Symbol卢
4年前
js垃圾回收机制原理给你聊的明明白白
前言大多数语言都是提供自动内存管理机制,比如C、Java,JavaScript。自动内存管理机制也就是我们经常听到的垃圾回收机制。好神奇哦,语言会收垃圾,哈哈😄,不过这里的垃圾,可不是家里面的厨余垃圾啥的,而是一些不再使用的变量所占用的内存。我们的js的执行环境会自动对这些垃圾进行回收,也就是释放那些不再使用的变量所占用的内存,收垃圾的过程会按照固定的
郜小超 郜小超
5年前
浅谈promise和js执行机制(二)
让我们继续上一次遗留的问题:setTimeout(function(){console.log('1')});newPromise(function(resolve){console.log('2');resolve();}).then(function(){console.log('3')});conso
Stella981 Stella981
4年前
Javascript解析机制 执行机制
HTML5学堂:在学习JavaScript过程中,我们需要了解事件的机制是怎么执行的?本文将会提到JavaScript事件机制的解析,希望对大家有帮助!javascript解析的过程主要分为两个阶段,分别是编译与执行阶段。在编译期,javascript解释器将完成对javascript代码的预处理,即将javascript代码转换为字节码。在执行
Stella981 Stella981
4年前
JavaScript:再谈Tasks和Microtasks
JavaScript是单线程,也就是说JS的堆栈中只允许有一类任务在执行,不可以同时执行多类任务。在读js文件时,所有的同步任务是一条task,当然了,每一条task都是一个队列,按顺序执行。而如果在中途遇到了setTimeout这种异步任务,就会将它挂起,放到任务队列中去执行,等执行完毕后,如果有callback,就把callback推入到Tasks中去,
Stella981 Stella981
4年前
AJAX与Django
AJAX什么是AJAX?AJAX不是JavaScript的规范,它的缩写:AsynchronousJavaScriptandXML,意思就是用JavaScript执行异步网络请求。提交任务之后,不原地等待,直接执行下一行代码,任务的返回通过回调机制。局部刷新,不整体刷新,而是界面莫个地方局部刷新AJAX原理
Stella981 Stella981
4年前
JavaScript 执行效率不行?因为你还没用 V8
作为当下使用最广泛的JavaScript引擎,V8的生态圈非常庞大,这与它革命性的设计密不可分。V8出现之前,所有JavaScript引擎用的都是解释执行的方式,这是JS执行速度过慢的主要原因;而V8引入的即时编译(JIT)双轮驱动设计,混合编译执行和解释执行两种手段,为JavaScript的执行速度带来了极大
Stella981 Stella981
4年前
JavaScript 基础
1.简介:  JavaScript(JS)是一种基于对象和事件驱动,可以与HTML标记语言混合使用的脚本语言。广泛用于客户端Web开发,常用来给HTML网页添加动态功能,比如响应用户的各种操作。其编写的程序可以直接在浏览器中解释执行。Javascript的国际标准是ECMAScript(由欧洲计算机制造商协会(ECMA)结合J
Stella981 Stella981
4年前
JavaScript:垃圾收集机制
  JavaScript具有自动垃圾收集机制。也就是说,执行环境会负责管理代码执行过程中使用的内存。开发人员不必关心内存分配和回收问题。  垃圾收集机制的原理:找到不再继续使用的变量,然后进行释放其占用的内存。所以,垃圾收集器会按照固定的时间间隔(或代码执行中设定的收集时间)持续执行这一操作。  垃圾收集器会跟踪哪些变量有用哪些变量没用,对没用的变量