html不执行javascript代码_V8是如何执行JavaScript代码的?

bcc2fca18e9cf22eb39635589354ce0b.png

编程语言是如何运行的

>

众所周知,我们通过编程语言完成的程序是通过处理器运行的。但是处理器不能直接理解我们通过高级语言(如C++、Go、JavaScript等)编写的代码,只能理解机器码,所以在执行程序之前,需要经过一系列的步骤,将我们编写的代码翻译成机器语言。这个过程一般是由编译器(Interpreter) 或者解释器(Compiler) 来完成。

那么编译器和解释器的工作流程是怎样的呢?

8869891404f54c4ae855f68207c16edb.png      512300b0fd12f0101f8e5d031c1b2ccd.png

从上图可以看出它们的大概的工作流程。那么既然编译器和解释器都可以完成代码翻译的工作,为何还同时存在呢?

这是因为编程语言有两个类别:静态类型和动态类型。静态类型的语言,比如C++、Go等,都需要提前编译 (AOT) 成机器码然后执行,这个过程主要使用编译器来完成;而动态语言,比如JavaScript、Python等,只在运行时进行编译执行 (JIT) ,这个过程通过解释器完成。

通过上面的描述,我们已经知道了JavaScript是通过解释器来进行翻译执行的,那么JavaScript引擎V8执行Js代码的详细过程是怎么样的呢?接下来我们详细分析一下。

V8执行JS代码的过程

>

V8执行Js代码的整体流程如下图所示:

7fed5dbdd08b54a4cddd9ac69e2ff3c4.png

在这个过程中,V8同时使用了Parser(解析器)、Ignition(解释器) 和TurboFan(编译器) 来执行Js代码。

> 1.Parser生成抽象语法树

在Chrome中开始下载Javascript文件后,Parser就会开始并行在单独的线程上解析代码。这意味着解析可以在下载完成后仅几毫秒内完成,并生成AST。

7c19e271b70e8be08c2fe31a4c665935.png

上图是一段Js代码转成AST后的结构图,从图中可以看出AST是把代码结构化成树状结构表示,这样做是为了更好的让编译器或者解释器理解。此外,AST还广泛应用于各类项目中,比如Babel、ESLint,那么AST的生成过程是怎么样的呢?

1. 词法分析(lexical analysis):主要是将字符流(char stream) 转换成标记流(token stream),字符流就是我们一行一行的代码,token是指语法上不能再分的、最小的单个字符或者字符串。

9ccad044471b05051c39a3caafd33f2b.png


var name = "ivweb"
//转成token后为

[
{
"type": "Keyword",
"value": "var"
},
{
"type": "Identifier",
"value": "name"
},
{
"type": "Punctuator",
"value": "="
},
{
"type": "String",
"value": "\"ivweb\""
},
{
"type": "Punctuator",
"value": ";"
}
]

从上面可以看出,var name = "ivweb"; 这样一段代码,会有关键字"var"、标识符"name"、赋值运算符"="、字符串"ivweb"、分隔符";",共5个token。

2. 语法分析:将前面生成的token流根据语法规则,形成一个有元素层级嵌套的语法规则树,这个树就是AST。在此过程中,如果源代码不符合语法规则,则会终止,并抛出“语法错误”。

2.Ignition生成字节码

ecec574090829f411d89d95a3027bda0.png

字节码是机器码的抽象,可以看作是小型的构建块,这些构建块组合到一起构成任何JavaScript功能。字节码比机器码占用更小的内存,这也是为什么V8使用字节码的一个很重要的原因。字节码不能够直接在处理器上运行,需要通过解释器将其转换为机器码后才能执行。

882f2c65cd5235d556b644d158927d9d.png

通过上图可以看出,Ignition把前一步得到的AST通过字节码生成器经过一些列的优化生成字节码。
在这个过程中:

  • Register Optimizer: 主要是避免寄存器不必要的加载和存储;

  • Peephole Optimizer: 寻找直接码中可以复用的部分,并进行合并;

  • Dead-code Elimination: 删除无用的代码,减少字节码的大小

通过上面三个过程的优化进一步减小字节码的大小并提高性能,最后Ignition执行优化后的字节码。

3.执行代码及优化

ab74600665266e1bf1385303cf887dd3.png

Ignition执行上一步生成的字节码,并记录代码运行的次数等信息,如果同一段代码执行了很多次,就会被标记为 “HotSpot”(热点代码),然后把这段代码发送给 编译器TurboFan,然后TurboFan把它编译为更高效的机器码储存起来,等到下次再执行到这段代码时,就会用现在的机器码替换原来的字节码进行执行,这样大大提升了代码的执行效率。


另外,当TurboFan判断一段代码不再为热点代码的时候,会执行去优化的过程,把优化的机器码丢掉,然后执行过程回到Ignition。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Node.js是一个基于Chrome V8引擎的JavaScript运行环境,可以在服务器端运行JavaScript代码。它不同于传统的浏览器端JavaScript,而是提供了一个独立的运行时环境,使得JavaScript可以直接在服务器端运行。 Node.js可以解析和执行JavaScript代码,它使用V8引擎将JavaScript代码转换为机器码,并在服务器端执行。这种能力使得开发者可以利用JavaScript的特性来编写服务器端程序,构建高性能、可伸缩的应用。 Node.js的特点之一是非阻塞式的I/O模型,这意味着它可以同时处理大量的并发请求,而不因为等待I/O操作而阻塞线程。这种特性使得Node.js非常适合开发实时应用、高并发的网络服务器和Web应用。同时,Node.js还提供了许多内置模块和第三方模块,使得开发者可以方便地构建各种类型的服务器应用。 除了在服务器端运行JavaScript,Node.js还可以作为构建工具和中间件平台来使用。通过使用Node.js的包管理器npm,开发者可以方便地安装、使用和分享JavaScript的包和模块。同时,Node.js还支持开发构建工具、自动化任务和前端开发工具等。 总而言之,Node.js是一个在服务器端运行JavaScript的运行环境,它提供了解析和执行JavaScript代码的能力,并通过非阻塞式的I/O模型实现高性能的服务器应用。其灵活性、高效性和生态系统的丰富性使得Node.js成为了广泛应用的服务器端开发工具。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值