JS引擎如何执行JS代码

编译性语言(C++\java)

在代码运行前编译器将代码转化为机器码,运行时候直接使用,不需要再次编译

解释性语言(JS)

在运行的时候将代码转化为机器码使用,弱类型语言=>在运行的时候才能确定其类型 目前的 TS 只是增加了编译时候的类型检测

总结

解释性语言的执行速度要慢与编译性语言

JS 引擎 为了提高执行速度(v8、jsCore)

执行过程

  • Parse:将 JS 代码转化为 AST
    • 词法分析
    • 语法分析
  • lgnition 阶段:将 AST 转化为字节码
  • TurboFan:根据上一阶段结果将字节码优化为可以执行的机器码
  • Orinoco:垃圾回收
  • 编译过程
  • 执行过程

词法分析

将字符流转化为 tokens,token 指的是语法上不能分割的最小单位;比如这行代码 var a =1;通常会被分解成 var 、a、=、2、

语法分析

token 生成 AST

生成字节码

由于直接转化为机器码会带来内存占用太大,而且有写场景更适合转化为字节码,字节码可以理解为机器码的抽象。

生成机器码

在生成字节码的过程中,如果刚发现一段 diamante 多次执行,生成的字节码以及分析会传给 TurBoFun 编译器,他会根据分析的数据生成机器码。主要是通过一种推测优化的技术,生成机器码 image

编译阶段

执行上下文创建(创建变量对象、作用域链、this)

  • 执行上下文创建

    执行上下文的穿件离不开 JS 的运行环境,其运行环境包括全局环境:第一次载入代码,会创建一个全局环境,直到应用程序退出才会销毁。

    函数环境: 当函数呗调用的时候,则就会进入该函数的运行环境,当该环境代码全部执行完毕,环境才会被销毁。eval。在不同的运行环境中,JS 都会创建一个新的执行上下文,该过程包括:

  1. 创建变量对象 每个执行上下文都会有一个关联的变量对象,改对象上会保存这个上下文中定义的所有变量以及函数。比如全局变量对象为 window,node 上的为 global.其过程有一下两点:
    • 创建 agrument 对象,检查函数声明(内存中创建函数,并初始化为函数对象)、变量声明(初始化赋值 undefine,执行时候赋值)【变量提升和函数提升就在这个阶段】
    • 词法环境-变量环境(let、function)和词法环境(let、const、class)。通过词法环境记录变量函数的声明
  2. 建立作用域链 将作用域通过某种方式链接起来。在编译阶段先创建变量对象、在执行阶段将变量对象激活为活动对象,通过外部的词法环境引用创建作用域链
  3. 确定 this

执行阶段

将编译阶段的执行上下文压入执行栈,执行上下文结束之后弹出