前言
-
细阅此文章大概需要 10分钟左右
-
本篇中简要讲述了如下内容:
- JS是一门编程语言
- V8
- js 代码编译过程
-
如果有任何问题都欢迎指正,我看到了就会回复/修改,如果我解决不了也可以一起探讨、学习。希望今后能和大家共同学习、进步。
-
下一篇会尽快更新,已经写好的文章也会在今后随着理解加深或者加入一些例如图解 代码块 并且断断续续的进行修改。
-
如果觉得这篇文章对您有帮助,您的点赞就是对我创作的最大激励
js 是一门编程语言
从编辑语言角度来看 可以分为三大类
- 机器语言: 10101001010 一些机器指令
- 汇编语言: bx 一些汇编指令
- 高级语言: go dart rust kotlin
而高级语言中也可以分为两大类:
- 编译性语言: C C++这一类语言就是编译过后变成可执行文件 随后计算机进行读取执行
- 解释性语言: js python 机器边读取源代码边进行解释 随后计算机进行执行
- (Java是啥类型语言由屏幕前的您来决定)
高级语言都是需要进行转化为机器指令来执行的 同时我们编写的 js 代码最后都是交付给 cpu 执行的 但是 cpu 只认识自己的指令集 实际上是机器语言 才能被 cpu 执行
所以我们需要 js 引擎帮助我们将 js 代码翻译成 cpu 指令来执行
浏览器内核和 js 引擎的关系: 由 webkit 为例 浏览器内核(webkit) = js 引擎(jscore)+布局引擎(webcore)
目前市面上JS引擎有很多 如JavaScriptCore、V8、SpiderMonkey 其中有一定代表意义的JS引擎就是V8,在V8出现之前所有JS虚拟机采用解释执行的原因 而V8采用了即时编译(JIT)的双轮驱动的设计模式
V8
V8 介绍
V8 是用 C++编写的 Google 开源高性能 javascript 和 webAssembly 引擎 它用于 Chrome 和 nodejs 它实现 ECMAScript 和 WebAssembly 同时 V8 可以独立运行也可以嵌入到任何 C++应用中
上面这段是维基百科上的原话我直接CV过来了
所以我们可知 目前咱们每天写的js代码是是通过V8编译 同时js是寄生于V8
js 代码编译过程
下图为V8编译流水线
-
js 代码通过 V8 的 Parse 模块 解析为 AST 抽象语法树 这一部分的核心就是对 例如
var redux所有的 js 语句进行 词法分析 & 语法分析 词法分析就是对每一个词进行扫描 一般就是 js 关键字 变量名 值 最后生成海量的 tokens 这些 tokens 会以一种数组对象方式进行存储 [{},{}] 比方说上面语句经过词法分析后的结构就是 tokens:[ { type: "keyword", value: "var" }, { type: "identifier", value: "redux" }, ];语法分析主要是生成 AST 语法抽象树 如果函数没有被调用 那么是不会被转换为 AST 的 在线 js 代码 AST 抽象语法树 astexplorer.net/
-
AST 抽象语法树通过 V8 内置 Ignition 模块 解释/转化 将 AST 抽象语法树转化为字节码 (bytecode) 这些字节码是跨平台的 无关各种系统 CPU 架构 字节码会转为不同平台上的指令 最后由 CPU 去运行结果 执行结果也会随之对应反映到我们浏览器中 同时也会收集 TurboFan 优化所需的信息(函数参数类型 有了类型才能进行技术)
-
V8 引擎有自己独特的性能优化的方面 如果每次字节码都转化为 CPU 指令集 显然这一步将耗费很多性能 所以 V8 引擎采用了一种类似 Redis 缓存 的功能 其实现就是内置模块 TurboFan
-
TurboFan 的核心功能就是搜集函数的执行信息(例如类型) 如果发现当前函数是一个执行频率比较高的函数 会将当前函数标记为 Hot Function 同时由 TurboFan 模块将当前函数变为 优化后的机器码(MachineCode) 当我们后续执行当前函数时根本就不需要再讲字节码转换为 CPU 指令集 直接执行机器指令的运算结果
-
但是 TurboFan 优化也是有问题的
const sum = (a, b) => a + b; sum(1, 2); sum("foo", "bar");上面执行背后是不同的 cpu 指令集 (一个是相加 一个是字符串拼接) 这时候 V8 引擎就会做反向优化(De optimization) 把机器指令又转换为字节码 后续转化为 CPU 指令集 运行结果 所以从这个角度出发 ts 代码是要比 js 代码运行效率稍显高点的