编译器和解释器
- 按语言的执行流程,可以把语言划分为编译型语言和解释型语言。
- 编译型语言:在程序执行前,需要经过编译器的编译过程,并且编译之后会直接保留机器能读懂的二进制文件,这样每次运行程序时,都可以直接运行该二进制文件,而不需要重新编译。
- 解释性语言:在程序运行时每次都需要通过解释器对程序进行动态解释和执行。
- 编译器工作流程:编译器依次对源代码进行词法分析、语法分析,生成抽象语法树(AST)——>词义分析生成中间代码——>代码优化生成二进制文件——>直接执行。
- 解释器工作流程:解释器对源代码精选词法分析、语法分析,生成抽象语法树(AST)——>词义分析生成字节码——>解释执行。
v8引擎是如何执行一段JS代码的
- 生成抽象语法树(AST)和执行上下文
- 分词(tokenize),又称词法分析,将源代码才接触一个个token(语法上不可能在分的、最小的单个字符或字符串)
- 解析(parse),又称语法分析,将分词阶段生成的token数据,根据语法规则转化为AST。如果源代码中存在语法错误,这一步就会终止,并抛出一个"语法错误"。
- 基于AST生成该段代码执行上下文。
- 生成字节码
- 解释器根据AST生成字节码,并解释执行字节码。
- 字节码是结于AST和机器码之间的一种代码,但是与特定类型的机器码无关,字节码需要通过解释器将其转换为机器码后才能执行。
- 字节码可以减少系统的内存使用。
- 执行代码
- 解释器会逐条解释执行字节码。
- 如果一段代码被重复执行多次,会被定义为"热点代码",那么编译器会把这段热点的字节码编译为高效的机器码,当再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,从而大大提高代码的执行效率。
- 即时编辑:解释器在解释执行字节码的同时,收集代码信息,当它发现某一部分代码变热之后,编译器会把热点的字节码转换为机器码,并把转换后的机器码保存起来以备下次使用。
JS性能优化
- 优化JS执行效率,聚焦在单词脚本的执行时间和脚本的网络下载上
- 提升单次脚本的执行速度,编码JS的长任务霸占主线程,这样可以使得页面快速响应交互。
- 避免大的内联脚本,因为在解析HTML的过程中,解析和编译也会占用主线程。
- 减少JS文件的容量,因为更小的文件会提高下载速度,并且占用更低的内存。