js引擎的工作原理,js是怎样处理事件的eventloop,宏任务源tasks和微任务源jobs分别有哪些?js是如何构造抽象语法书(AST)的?

js引擎只执行同步任务, 异步任务会有工作线程来执行,当需要进行异步操作(定时器、ajax请求、dom事件注册等), 主线程会发一个异步任务的请求, 相应的工作线程接受请求; 当工作线程完成工作之后, 通知主线程;主线程接收到通知之后, 会执行一定的操作(回调函数)。主线程和工作线程之间的通知机制叫做事件循环。

调用栈 (call stack): 主线程执行时生成的调用栈
任务队列 (task queue): 工作线程完成任务后会把消息推到一个任务队列, 消息就是注册时的回调函数
在这里插入图片描述

当调用栈为空时, 主线程会从任务队列里取一条消息并放入当前的调用栈当中执行, 主线程会一直重复这个动作直到消息队列为空。 这个过程就叫做事件循环 (event-loop)。

关于宏任务和微任务,参考 事件流、事件模型、事件循环概念理解? 浏览器线程理解与microtask与macrotask

ES6新引入了Promise标准,同时浏览器实现上多了一个microtask微任务概念。在ECMAScript中,microtask称为jobs,macrotask可称为task。

macrotask宏任务tasks,也就是上面说到的任务队列的任务。执行栈上的每个任务都属于宏任务,主线程执行完执行栈的任务,从任务队列取新的任务。宏任务执行时不会中断,会一次性执行完,为了及时渲染数据,主线程执行完一个宏任务之后,会执行一次渲染。
task–》渲染 --》宏任务 --》渲染 …

microtask微任务jobs,可以看成是插队需要及时处理的任务,会在当前主线程task任务执行后,渲染线程渲染之前,执行完当前积累所有的微任务。
task–》jobs --》渲染 --》宏任务 --》jobs --》渲染 …

AST 参考:程序语言进阶之DSL与AST实战解析

将抽象语法树之前要先了解下NLP中文法的概率。任何一种语言,具体说就是DSL,都有自己的一套文法,用来表示这套语言的逻辑规范。不同的文法写出来的语法表达式也不一样。我们根据语法表达式来解析语言,就可以形成一个AST抽象语法树。然后可以作进一步处理。我常用的是PEG解析表达式语法。可以很轻松的写出语法的每一条产生式规则,来构造生成AST。所谓AST可以理解成按照一定语法结构组成的词汇流,每个词汇有特定的语法含义,比如说这是一个声明,这个一个操作符等等。
在这里插入图片描述

上面这个图是苹果最早做的KHTML渲染引擎中的KJS(javascript引擎),他是基于AST来实现的JavaScript语言解析的,先通过词法分析得到JSTokens流,然后经过语法分析得到抽象语法树,然后经过字节码生成器,转换成字节码。字节码经过JavaScript虚拟机JIT编译成机器码,然后执行。这是最初的设计架构,后来苹果公司基于此重构出了webkit渲染引擎,google基于webkit单独维护,称为blink渲染引擎,chrome的JS引擎改造为V8引擎。参考:简述Chromium, CEF, Webkit, JavaScriptCore, V8, Blink

举个例子常用的babel插件的原理就是基于babylon词法语法分析器生成抽象语法树,将代码文本转换成按照特定语法组合的token流集合,然后经过babtlon-traverse这个组件来负责处理遍历语法树,访问每个token节点,通过对token的处理,可以生成我们需要的AST语法树,然后再通过babylon-generator这个组件来做代码生成,根据AST生成代码。比如可以将 箭头函数 转换成 function函数。

浏览器中,通过开发者调试工具分析就能看到,下载完js脚本后,首先浏览器要先解析代码=》初始化上下文环境=》执行代码,整个是evaluate script的过程,解析代码的过程也是编译js的过程所以看最前面第一步就是compile script,将js代码编译成字节码(这一块涉及到浏览器js引擎的优化,v8引擎是编译成字节码,后面经过JIT解析执行(这个参考 你不知道的LLVM编译器 可以提升效率做动态优化), 这个类似于java、C#这些需要将源代码编译成中间语言,然后在虚拟机执行,javascript编译成字节码后面也是在虚拟机执行),然后就开始执行脚本。
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章