跳到主要内容

JS执行过程

image-20240327131557992

JS 引擎有三大核心组件:解析器(Parser)、解释器(Ignition)、和编译器(TurboFan)

  1. 源码首先进入解析器,将源码经过词法分析语法分析后解析为 AST。这个过程同时也会发生变量提升作用域链机制也在这里体现

  2. 解释器首先将 AST 转换为字节码,然后逐行执行。这个过程同时也会生成执行上下文对象

说编译器之前,首先介绍下字节码和机器码

  • 字节码不占空间,但是执行慢

  • 机器码占空间,但是执行快

二者结合的方案就是 JIT(Just In Time),这时编译器就闪亮登场了

  1. 当 JS 引擎中的监控模块发现一段代码被多次调用,就会被标记为热代码。编译器就会将这段热代码编译为机器码缓存下来,供下次调用。提升执行效率

关于提升

为什么会出现提升

JavaScript 出现变量提升现象的原因在于在解释器执行代码前,需要根据解析器解析出来的 AST 进行执行上下文和代码解析机制,为变量、函数等声明分配内存空间

关于作用域与作用域链以及执行上下文,都有额外的文章讨论。下面着重介绍下变量提升的机制

以下内容摘自 mdn

JavaScript 提升是指解释器在执行代码之前,似乎将函数变量导入声明移动到其作用域的顶部的过程

发生在解析器将源码解析为 AST 之后,解释器执行代码之前。

用通俗的话来说,提升的行为主要有以下四种情形

  1. 能够在声明变量之前在其作用域中使用该变量的值(函数、import)
  2. 能够在声明变量之前在其作用域中引用该变量而不抛出 ReferenceError,但值始终是 undefined。(var)
  3. 变量的声明导致在声明行之前的作用域中行为发生变化。(tdz,let const)
  4. 声明的副作用在评估包含该声明的其余代码之前产生。(import)

四种 function 声明的提升表现为第 1 种行为;

var 声明的提升表现为第 2 种行为;

letconstclass 声明的提升表现为第 3 种行为;

import 声明的提升表现为第 1 和第 4 种行为。