目录

JavaScript运行原理

# JavaScript代码执行

浏览器内核由两部分组成

  • webCore:负责解析HTML,布局,渲染等等
  • JavaScriptCore:解析执行JavaScript代码

代表性的JavaScript引擎是Chrome浏览器的V8引擎

# V8引擎执行原理

# V8引擎定义

  • V8是用C ++编写的Google开源高性能JavaScript和WebAssembly引擎,它用于Chrome和Node.js等
  • 它实现ECMAScript和WebAssembly,并在Windows 7或更高版本,macOS 10.12+和使用x64,IA-32,ARM或MIPS处理器的Linux系统上运行
  • V8可以独立运行,也可以嵌入到任何C ++应用程序中。

image

# V8引擎架构

  • Parse模块会将JavaScript代码转换成AST(抽象语法树),这是因为解释器并不直接认识JavaScript代码,如果函数没有被调用,那么是不会被转换成AST的
  • Ignition是一个解释器,会将AST转换成ByteCode(字节码),同时会收集TurboFan优化所需要的信息(比如函数参数的类型信息,有了类型才能进行真实的运算),如果函数只调用一次,Ignition会解释执行ByteCode
  • TurboFan是一个编译器,可以将字节码编译为CPU可以直接执行的机器码;
    • 如果一个函数被多次调用,那么就会被标记为热点函数,那么就会经过TurboFan转换成优化的机器码,提高代码的执行性能;
    • 但是,机器码实际上也会被还原为ByteCode,这是因为如果后续执行函数的过程中,类型发生了变化(比如sum函数原来执行的是number类型,后来执行变成了string类型),之前优化的机器码并不能正确的处理运算,就会逆向的转换成字节码;

# 初始化全局对象

js引擎会在执行代码之前堆内存创建一个全局的对象(Global Object (GO));

  • 该对象那在所有的作用域中都可以访问
  • 构建的对象包括 Date, Arrary, Number, setTimeOut, setInterval等
  • 其中有一个window属性指向自己
  • 在对应的主机环境下会创建对应的全局对象,例如在浏览器环境下创建document对象, 在Node环境下创建Node环境下的全局对象

image

# 执行上下文

js引擎内部有一个执行上下文栈(Execution Context Stack,简称ECS),用于执行代码的调用栈。执行的是全局的代码块,全局的代码块为了执行会构建一个Global Execution Context(GEC);GEC被放到ECS中执行

GEC被放入到ECS中包含两部分内容

  • 在执行代码前,在parser转成AST的过程中,会将全局定义的变量、函数等加入到GlobalObject中,但是并不会复制;这个过程也称之为变量的作用域提升
  • 在代码执行中,对变量赋值,或执行其他的函数。

英文文档翻译

当代码块被翻译成ECMAScript可执行的代码时,代码块进入执行上下文。活跃的执行上下文在逻辑上形成栈。栈结构中顶层的逻辑上下文就是正在运行的执行上下文。

# VO对象 (Variable Object)

每一个执行上下文会关联一个VO,变量和函数声明会被添加到这个VO对象中;当全局代码被执行的时候,VO就是GO对象了。

# 函数执行过程

在执行的过程中执行到一个函数时,就会根据函数体创建一个函数执行上下文(Function Execution Context,简称FEC),并且压入到EC Stack中

因为每个执行上下文都会关联一个VO,那么函数执行上下文关联的VO是

  • 当进入一个函数执行上下文时,会创建一个AO对象(Activation Object)
  • 这个AO对象会使用arguments作为初始化,并且初始值是传入的参数
  • 这个AO对象会作为执行上下文的VO来存放变量的初始值

# 作用域和作用域链

当进入到一个执行上下文时,执行上下文也会关联一个作用域链

  • 作用域链是一个对象列表,用于变量标识符的求值
  • 当进入一个执行上下文时,这个作用域链被创建,并且根据代码类型添加一系列的对象。
最近更新
01
防抖和节流
02-06
02
正则表达式
01-29
03
async_await函数
12-30
更多文章>