JavaScript 运行原理

588 阅读3分钟

1.JavaScript是一门高级的编程语言

  • 机器语言:100010001000,一些机器指令;
  • 汇编语言:mov ax bx,一些汇编指令;
  • 高级语言:C、C++、Java、JavaScript、Python; 最终运行都是要转换成机器语言来运行的。

2. 浏览器的工作原理

Snipaste_2022-03-11_21-20-09.png

3.浏览器的内核

  • Gecko: 早期网景浏览器和火狐浏览器内核
  • Trident:微软IE浏览器,现在已经转向新的Edge浏览器(Blink内核)
  • Webkit:苹果safari浏览器内核
  • Blink:谷歌Chrome浏览器内核

4.浏览器渲染过程

Snipaste_2022-03-11_21-41-07.png

  • 浏览器首先解析html文件时,按自上而下的顺序解析,如果过程中遇到了JavaScript标签,则会停止解析,浏览器会将控制权给到js引擎,js引擎去加载和执行js代码
  • 通过解析html标签和js代码得到对应的DOM树,与Css的样式规则相结合形成渲染树(Render Tree)
  • 渲染树的每个元素包含的内容都是计算过的,它被称之为布局layout。浏览器使用一种流式处理的方法,只需要一次pass绘制操作就可以布局所有的元素。
  • 将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting.
  • 最终展示页面

5. V8引擎的执行原理

V8引擎是目前比较强大的JS引擎,由C++编写,可以独立运行,也可以嵌入到任何C++应用中。

Snipaste_2022-03-11_22-10-34.png

  • parse模块:语法解析和词法解析,将JS源码转化为AST抽象语法树,转换的AST语法树有点类似JSON格式。astexplorer.net/ 在线解析网址如图:

Snipaste_2022-03-11_22-15-49.png

babel的实现原理就类似于这种,先将ES6语法转为抽象语法树,再将抽象语法树,转为ES5。

  • lgnition:是一个解释器,它会将AST抽象语法树,转成字节码。同时会帮助TurboFan模块收集所需要的信息(比如函数参数的类型信息)
  • TurboFan:是一个编译器:它会将字节码编译成机器码。如果一个函数多次调用,就被被它标记成热点函数,并被TurboFan转换成优化的机器码,提高机器执行性能。但是如果后续执行中函数的参数类型变化了,会逆向优化成字节码

6. 初始化全局对象

js引擎在执行代码前,会在堆内存中创建一个全局对象:Golbal Objcet(GO)

  • 该对象所有的作用域都可以访问到
  • 里面会包含一些内置的方法Date、String、setTimeout等等
  • 也包含一个window属性指向自己

7. 执行上下文栈

  • js引擎内部有一个执行上下文栈(Execution Context Stack 简称ECS),是用于执行代码的调用栈
  • 执行的是全局的代码块
    • 全局的代码块为了执行会创建一个 Global Execution Context (GEC)
    • GEC会被放到ECS中去执行
  • GEC被放到ECS中包含两部分内容
    • 第一部分:在代码执行前,在parser转成AST的过程中,会将全局定义的变量、函数等加到GO中,但是并不会赋值。这个过程也被称作变量提升
    • 第二部分:在代码执行中,对变量赋值,或者执行其他函数

8. 函数执行上下文

  • 执行上下文栈在遇到函数的时候,就会根据函数体创建一个函数执行上下文(Functional Execution Context 简称FEC),并且压入到ECS中
  • FEC中包含三部分
    • 第一部分: 在解析函数成为AST树结构时,会创建一个Activation Object(AO)。AO中包含形参、arguments、函数定义和指向函数的对象,定义的变量
    • 第二部分: 作用域链:由VO(在函数中就是AO)和父级AO组成,查找时会一层层查找。
    • 第三部分: this绑定的值