Skip to content

学习JavaScript引擎执行机制

Posted on:March 23, 2022 at 10:23 PM

此博文用于记录学习浏览器的 JavaScript 引擎执行机制的一些知识点,可用于解决以下的问题:

  1. JavaScript 是单线程语言,是如何实现异步的?
  2. JavaScript 引擎的 event loop 机制是怎样的?
  3. 谈谈 async/await 和 promise 的执行顺序

JavaScript 的单线程特性与异步

为什么 JavaScript 是单线程的?

首先要考虑到 JavaScript 设计之初就是为了用于浏览器上。假设: JavaScript 是多线程的,当浏览器渲染页面的时候分别有:线程 1 和线程 2,两者同时操作同一个 dom 节点。 线程 1 命令删除该节点,而线程 2 命令编辑此节点。两个线程的指令同时指定给同一个 dom 节点,且指令是矛盾的,浏览器就不知道怎么执行了。(有点像后端多线程针对同一个数据库资源分别进行读写操作)

为什么 JavaScript 需要异步?

反向思考,假如 JavaScript 不支持异步,那么在 JavaScript 执行的过程中,如果出现某段代码执行时间过长,导致下面的代码被阻塞了,出现长时间的卡死,导致功能不完整,甚至功能不可用,最终给用户很差的用户体验。

有了异步执行,JavaScript 可以灵活地处理代码的执行,开发人员在开发的过程中会知道哪些需要同步处理,哪些可以异步处理。

单线程的 JavaScript 如何实现异步?

JavaScript 是通过事件循环机制(event loop)来实现异步的,事件循环机制也就是 JavaScript 的执行机制(浏览器端和 nodejs 端的事件循环机制会有一点差别,这里不做展开)。

JavaScript 的事件循环机制

同步任务和异步任务?

为了容易的理解,先将 JavaScript 的任务分为两类:同步任务和异步任务。

JavaScript 在执行代码的时候会判断当前任务类型是什么,如果是同步任务则进入主线程中按顺执行,而异步任务则进入任务队列当中,等待 JavaScript 引擎的调用。当某个异步任务被 JavaScript 调用的时候,会离开任务队列而进入主线程执行(如果此异步任务有回调函数的话,否则就不需要进入主线程)。

主线程顾名思义就是 JavaScript 唯一的执行线程,里面的任务是按顺序执行。而任务队列则是异步任务等待执行的地方。

当主线程的任务全部完成了,JavaScript 引擎就会检查任务队列中异步任务,是否可以进入主线程了。

宏任务和微任务

到这里就基本认识了 JavaScript 的循环机制,但实际上并不能简单地将任务划分为同步任务和异步任务两种,而是应该划分为 宏任务微任务

事件循环执行顺序

特点:

参考链接: