引言
目前各种前端框架层出不穷,我们只有掌握底层本质的知识才能轻松理解上层应用,本来将从v8执行机制角度说明白一些概念和原理。
1. 编译器和解释器
由于机器不能直接理解我们的代码,所以在执行程序之前,需要将代码翻译成机器能读懂的机器语言。
编译型语言
:对源代码进行词法分析、语法分析生成抽象语法树(AST)--> 优化代码 --> 生成机器码。编译成功生成一个可执行的二进制文件。
解释型语言
:对源代码进行词法分析、语法分析生成抽象语法树(AST)--> 生成字节码 --> 执行程序、输出结果
v8在执行过程中既有解释器又有编译器。
2. 抽象语法树(AST)
抽象语法树是一种数据结构,是代码结构化的表示,编译器或者解释器都依赖AST。 常见的两个应用场景:
babel
就是利用AST将es6转换为AST,再将es6语法的AST转换为es5语法的AST,最后利用es5的AST生成JavaScript源代码。
eslint
检查JavaScript编码规范,也是将源码转换为AST,再利用AST来检查代码规范问题
生成过程:先分词再解析
分词(词法分析):将一行行源码拆解成一个个token(不能再分的单个字符或者字符串),例如var myName = '极客时间';就可以分为关键字var、标识符name、赋值运算符=和字符串dd四个token。
2. 解析(语法分析):将上一步生成的token数据根据语法规则转为为AST
有了AST,v8就会生成该代码的执行上下文参考上篇文章。
3. 字节码(Bytecode)
有了AST和执行上下文,解释器会根据AST生成字节码,并解释执行字节码。
一开始v8没有字节码,而是直接将AST转换为机器码(消耗内存),移动端内存占用问题明显引入了字节码。
字节码
就是介于AST和机器码之间的一种代码,需要解释器讲起转换为机器码后才能执行。
因为字节码占用的空间比较小,所以可以减少内存占用。
4. 即时编译器(JIT)
解释器在执行字节码过程中,如果发现有热点代码(一段代码被重复执行多次),编译器就会把这段热点的字节码编译为机器码。 这种字节码配合解释器和编译器的技术称为即时编译(JIT)
。
通过上面概念的分析,v8执行代码主要有3个过程:
生成抽象语法树和执行上下文
基于AST生成字节码
通过解释器执行代码及通过编译器优化编译字节码
优化执行效率
了解以上流程,那么应该如何优化JavaScript执行效率?
提升单次脚本的执行速度,避免JavaScript的长任务霸占主线程
避免大的内联脚本,因为在解析html的过程中,解析和编译也会占用主线程,尽量使用异步加载aync或defer
减少JavaScript文件的容量,提升网络下载速度及占更低的内存
总结
通过本文我们了解了v8执行JavaScript的流程,相信明白了这些底层知识即使技术不断迭代我们也不会感到慌了。
原文;https://juejin.cn/post/7098549234160369672