前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS代码是怎么被执行的

JS代码是怎么被执行的

作者头像
ek1ng
发布2023-03-08 14:38:21
3.1K0
发布2023-03-08 14:38:21
举报
文章被收录于专栏:ek1ng的技术小站

JS代码是怎么被执行的

我们看到的JS都是在浏览器中或者在Node环境中运行的对吧,那不论是浏览器还是Node,负责编译并且解释执行JS代码的都是一个叫做V8的东西,所以这个问题其实就是V8引擎是怎么去运行JavaScript的,而js和C/C++/Go/Rust这类静态编译的语言不同,这些静态编译的语言通过编译器把代码变成机器码,然后在机器上运行,js呢在编译后会生成字节码,然后在v8的虚拟机上运行字节码,java和python也有自己的虚拟机实现,这些语言都将生成的字节码放在虚拟机上运行,相比于直接以机器码运行的语言,这些语言在损失了性能的同时又获得了更多功能上的遍历,然后我们回到V8引擎是如何执行JS的问题。

img
img

我们这里以V8引擎的模块实现为索引来讲

V8 的 Parser 模块

Parser是V8的一个子模块,它负责将JavaScript源码转换成AST

词法分析

在词法分析过程中会将由字符组成的字符串分解成的词法单元(Token)。

image-20230204122527701
image-20230204122527701

Input:

代码语言:javascript
复制
// Life, Universe, and Everything
var answer = 42;

Output:

代码语言:javascript
复制
[
    {
        "type": "Keyword",
        "value": "var"
    },
    {
        "type": "Identifier",
        "value": "answer"
    },
    {
        "type": "Punctuator",
        "value": "="
    },
    {
        "type": "Numeric",
        "value": "42"
    },
    {
        "type": "Punctuator",
        "value": ";"
    }
]
语法分析

将词法单元变成抽象语法树(Abstract Syntax Tree,AST)

Input 为词法分析 的 Output

Output

代码语言:javascript
复制
{
  "type": "Program",
  "body": [
    {
      "type": "VariableDeclaration",
      "declarations": [
        {
          "type": "VariableDeclarator",
          "id": {
            "type": "Identifier",
            "name": "answer"
          },
          "init": {
            "type": "Literal",
            "value": 42,
            "raw": "42"
          }
        }
      ],
      "kind": "var"
    }
  ],
  "sourceType": "script"
}

可以在这个网站自己动手看看token和AST的样子。

V8 的 Ignition && TurboFan 模块

Ignition:interpreter,即解释器,负责将AST转换为字节码(Bytecode)并解释执行。

字节码是介于AST和机器码的一种代码,需要通过解释器转换成机器码后执行。一开始V8并没有Bytecode这个中间过程,而是直接将AST转换成机器码,但是由于内存占用问题,虽然机器码效率最高,但机器码占用的内存空间远超过字节码,需要消耗大量内存来放转换后的字节码,所以V8团队选择了时间换空间的策略,转变成了现在的AST->Bytecode->机器码。

img
img

TurboFan:compiler,即编译器,利用Ignition所收集的类型信息,将Bytecode转换为优化的汇编代码。

那么Ignition作为解释器,可以完成AST到字节码的转换过程并且担任解释执行的工作,为什么V8还需要TurboFan这个编译器呢,我们不是说Javascript是一种解释型语言吗?

实际上呢在现代的编程语言中解释型语言像JS为了功能上的需要,会引入JIT这样的技术

JIT (Just-In-Time)技术

通常,如果有一段第一次执行的字节码,解释器 Ignition 会逐条解释执行。在执行字节码的过程中,如果发现有热点代码(HotSpot),比如一段代码被重复执行多次,这种就称为热点代码,那么后台的编译器 TurboFan 就会把该段热点的字节码编译为高效的机器码,然后当再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,这样就大大提升了代码的执行效率。这种采用字节码结合编译器和解释器的技术,就是Just-In-Time也就是JIT,Python和Java的虚拟机实现也是用了JIT技术的。

了解JIT后我们也能知道为什么解释器Interpreter和编译器Compiler要叫做Ignition和TurboFan了,这是因为解释器 Ignition 是点火器的意思,编译器 TurboFan 是涡轮增压的意思,寓意着代码启动时通过点火器慢慢发动,一旦启动,涡轮增压介入,其执行效率随着执行时间越来越高效率,因为热点代码都被编译器 TurboFan 转换了机器码,直接执行机器码就省去了字节码“翻译”为机器码的过程。

img
img
img
img
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023年2月4日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • JS代码是怎么被执行的
    • V8 的 Parser 模块
      • 词法分析
      • 语法分析
    • V8 的 Ignition && TurboFan 模块
      • JIT (Just-In-Time)技术
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档