JavaScript基础系列开篇:V8是如何运行JavaScript(let a = 1)代码的?

简介: 我们知道,机器是不能直接理解我们平常工作或者自己学习的代码的。所以,在执行程序之前,需要将代码翻译成机器能读懂的机器语言。按语言的执行流程,可以把计算机语言划分为编译型语言和解释型语言

image.png


你就说吧,有没有资格,有没有资格,有没有资格,肯定有资格的。哈哈。因为我大致了解清楚了,也大致搞明白了一点了。


我们知道,机器是不能直接理解我们平常工作或者自己学习的代码的。所以,在执行程序之前,需要将代码翻译成机器能读懂的机器语言。按语言的执行流程,可以把计算机语言划分为编译型语言和解释型语言:


编译型语言:在代码运行前编译器直接将对应的代码转换成机器码,运行时不需要再重新翻译,直接可以使用编译后的结果。


解释型语言:需要将代码转换成机器码,和编译型语言的区别在于运行时需要转换。解释型语言的执行速度要慢于编译型语言,因为解释型语言每次执行都需要把源码转换一次才能执行。


Java 和 C++ 等语言都是编译型语言,而 JavaScript 是解释性语言,它整体的执行速度会略慢于编译型的语言。V8 是众多JavaScript引擎中性能表现最好的一个,并且它是 Chrome 的内核,Node.js 也是基于 V8 引擎研发的。


1.运行的整体过程


image.png


2.英译汉翻译的过程


比如我们看到了google V8官网的一篇英文文章 v8.dev/blog/faster…,在阅读的过程中,可以就是要对每一个单词进行解析翻译成中文,然后多个单词进行语法的解析,再通过对整句话进行整个语句进行解析,那么这句话就翻译结束了。


下面我们就举例一句英文的翻译过程:I am a programmer。


  • 1、首先对输入的字符串I am a programmer。进行拆分便会拆分成 Iamaprogrammer


相当于词法分析


  • 2、I 是一个主语, am 是一个谓语, a是一个形容词, programmer是个名词, 标点符号。


  • 3、I的意思, am的意思, a一个的意思, programmer程序员的意思, 句号的意思。


2和3一起相当于语法分析


  • 4、对3中的语法分析进行拼接处理:我是一个程序员。当然这是非常简单的一个英译汉,一篇文章的话,就会复杂一些了。


相当于语义分析


3.V8运行的整个过程


3.1.准备一段JavaScript源代码


let a = 10


3.2.词法分析:


一段源代码,就是一段字符串。编译器识别源代码的第一步就是要进行分词,将源代码拆解成一个个的token。所谓的token,就是不可再分的单个字符或者字符串。


3.3.token


esprima.org/demo/parse.… 可以查看生成的tokens,也就是上面那段源代码生成的所有token。


Token类别: 关键字、标识符、字面量、操作符、数据类型(String、Numeric)等


image.png


3.4.语法分析


将上一步生成的 token 数据,根据语法规则转为 AST。通过astexplorer.net 可以查看生成AST抽象语法树。


3.5.AST


生成的AST如下图所示,生成过程就是先分词(词法分析),再解析(语法分析)


image.png


当然你也可以查看生成的AST的JSON结构


{
  "type": "Program",
  "start": 0,
  "end": 9,
  "body": [
    {
      "type": "VariableDeclaration",
      "start": 0,
      "end": 9,
      "declarations": [
        {
          "type": "VariableDeclarator",
          "start": 4,
          "end": 9,
          "id": {
            "type": "Identifier",
            "start": 4,
            "end": 5,
            "name": "a"
          },
          "init": {
            "type": "Literal",
            "start": 8,
            "end": 9,
            "value": 1,
            "raw": "1"
          }
        }
      ],
      "kind": "let"
    }
  ],
  "sourceType": "module"
}


同样我在本地下载了v8,直接用v8来查看AST


v8-debug  --print-ast hello.js


image.png


3.6.解释器


解释器会将AST生成字节码,生成字节码的过程也就是对AST抽象语法树进行遍历循环,并进行语义分析


3.7.字节码


在最开始的V8引擎中是没有字节码,是直接将AST转换生成为机器码。这种架构存在的问题就是内存消耗特别大,尤其是在移动设备上,编译出来的机器码占了整个chorme浏览器的三分之一,这样为代码运行时留下的内存就更小了。 于是后来在V8中加入了Ignition 解释器,引入字节码,主要就是为了减少内存消耗。 本地可以使用V8命令行查看生成的字节码


v8-debug  --print-bytecode hello.js


image.png


3.8.热点代码


首先判断字节码是否为热点代码。通常第一次执行的字节码,Ignition 解释器会逐条解释执行。在执行的过程中,如果发现是热点代码,比如for 循环中的代码被执行了多次,这种就称之为热点代码。那么后台的TurboFan就会把该段热点代码编译为高效的机器码,然后再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了, 这样就大大提升了代码的执行效率。


3.9.编译器


TurboFan编译器也可以说是JIT的即时编译器,也可以说是优化编译器。


Ignition 解释器: 可以将AST生成字节码,还可以解释执行字节码。


4、总结


  • 了解V8整个的运行机制
  • 学习JavaScript到底是怎么运行的
  • 对日后编写JavaScript代码有非常多的好处
  • 看完学习了,能提升我们的技术水平
  • 对于日后遇到问题,能够从底层去思考问题出在那里,更快速的定位和解决问题
  • 真的非常熟悉了,可以自己开发一门新的语言
目录
相关文章
|
18天前
|
JSON JavaScript 前端开发
JavaScript原生代码处理JSON的一些高频次方法合集
JavaScript原生代码处理JSON的一些高频次方法合集
|
1月前
|
存储 JavaScript 前端开发
非常实用的JavaScript一行代码(整理总结)
非常实用的JavaScript一行代码(整理总结)
30 0
|
1月前
|
JavaScript 前端开发 测试技术
如何编写JavaScript模块化代码
如何编写JavaScript模块化代码
12 0
|
1月前
|
机器学习/深度学习 前端开发 JavaScript
实用的javascript代码分享
32个史上最有用的js代码
30 1
|
1月前
|
JSON 前端开发 JavaScript
16个重要的JavaScript代码
16个重要的JavaScript代码
32 1
|
1月前
|
JavaScript 前端开发 开发者
js开发:请解释什么是ES6的let和const关键字,以及它们与var关键字的区别。
ES6引入`let`和`const`替代`var`声明变量。`let`有块级作用域,存在暂时性死区,不进行变量提升,可重新赋值。`const`用于常量,值不可变但引用类型内容可变,同样有块级作用域和暂时性死区。与`var`主要区别在于作用域、变量提升和可变性。这些改进提高了代码的可预测性和安全性。
24 2
|
1月前
|
JavaScript
当当网新用户注册界面——JS代码
当当网新用户注册界面——JS代码
7 0
|
1月前
|
JavaScript
当当网首页——JS代码
当当网首页——JS代码
11 1
|
1月前
|
JavaScript Java
什么?java中居然可以执行js代码了?真是不知者不怪
什么?java中居然可以执行js代码了?真是不知者不怪
13 1
|
1月前
|
JavaScript 前端开发 Python
生成X-Bogus的js代码,通过python调用生成
该文本是一个关于如何解析和执行JavaScript代码的步骤说明。主要内容包括: 1. 找到JavaScript文件的位置。 2. 下载代码并进行格式化。 3. 运行代码时会出现缺少变量错误,需要添加模拟环境的代码。 4. 指出主要的入口函数是`_0x5a8f25`,将其赋值给`window`。 5. 提供了整个JavaScript代码的长串内容。 6. 提供了一个Python脚本,用于调用这个JavaScript函数并处理返回的数据。 总结:这段文本描述了如何处理和运行一个JavaScript文件,以及使用Python来与这个脚本交互的示例。