一文看遍JavaScript运行机制

274 阅读3分钟

前言

本文宗旨是了解清楚JavaScript代码是如何运行的,这里探讨的是基本运行机制。

不涉及语法方面知识,不涉及浏览器等导致实际效果差异,会以chrome浏览器,ES6语法来进行说明。

主要包含以下几个部分:

  • JavasScript引擎
  • 执行栈
  • this
  • 事件循环

JavasScript引擎

定义

JavaScript引擎是处理JavaScript脚本的运行环境,包括编译、解释、执行等操作。

特点

  • 单线程:同一时间,只能处理一件事情。
  • 多宿主环境:可以应用于浏览器、Node、其他webview容器中
  • 混合编译机制: 由于JavaScript脚本语言特性,所以基本机制是解释执行。但是为了提升执行性能,引入java等编译执行语言特性,将JavaScript代码编译成机器码。
  • 实时编译: JIT(Just-In-Time)。同样是为了提升性能,引入JIT机制,执行到哪一行,才会解析哪一行。
  • 内存回收:非常强势的内存管理策略,一切在运行堆栈里无用的数据都会被强行回收,从而可以大大提高JS代码的运行效率。

基本构成

  • 第一, 编译器。主要工作是将源代码编译成抽象语法树,然后在某些引擎中还包含将抽象语法树转换成字节码。
  • 第二, 解释器。在某些引擎中,解释器主要是接受字节码,解释执行这个字节码,然后也依赖来及回收机制等。
  • 第三, JIT工具。一个能够能够JIT的工具,将字节码或者抽象语法树转换成本地代码,当然它也需要依赖牢记
  • 第四, 垃圾回收器和分析工具(profiler)。它们负责垃圾回收和收集引擎中的信息,帮助改善引擎的性能和功效。

编译器

在正式执行JS前,还有一个预处理阶段,包括变量提升,分好补全等。

解释器

最初JS引擎就只是一个解释器,用来解释JavaScript脚本。

完整的的处理过程如下:

1、读取代码,进行词法分析(Lexical analysis),然后将代码分解成词元(token)

2、对词元进行语法分析(parsing),然后将代码整理成语法树(syntax tree)

3、使用翻译器(translator),将代码转为字节码(bytecode)

4、是用字节码解释器(bytecode interpreter),将字节码转为机器码

分号补全

JS执行是需要分号的,但是我们常常不写分号,为什么还能正常运行呢?

原因是,JS解释器有一个Semicolon Insertion规则,它会按照一定的规则,在适当的位置补充分号。

比如:

  • 当有换行符(包括含有换行符的多行注释),并且下一个token没法跟前面的语法匹配时,会自动补分号。
  • 当有}时,如果缺少分号,会补分号
  • 当源代码结束时,如果缺少分号,会补充分号

一个经典的错误

function test(){
	return
  {
  	a: 'a'
  }
}
test(); // undefined

变量提升

执行栈

作用域

全局作用域,函数作用域,模块作用域

BO&AO

词法环境&变量环境

递归

闭包

this

call,apply,bind

事件循环

宏任务、微任务

setTimeout,setInterval和requestAnimationFrame

Promise

ajax

总结

思维导图

实战题

参考资料

www.jianshu.com/p/565dfad8d… www.cnblogs.com/onepixel/p/…