浅谈js预编译

240 阅读2分钟

大家好,我是鼠目。「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战

本文主要谈论javaScript预编译。

javaScript是解释性语言

众所周知,javascript是一门解释性语言,也就是即时编译。它与传统编译型语言不同,并不需要提前将源码编译生产机器语言。(计算机并不能直接识别高级语言)而是通过内置的js引擎,在代码执行前的极短时间内,进行编译。也就是预编译。

tips: java有提前编译步骤,但是不是编译成机器码直接在计算机中直接运行,而是编译成字节码在JVM中运行。所以,java在我看来不算是严格的编译型语言。

js引擎执行js代码的三部曲。

  1. 词法分析(会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元)

  2. 预编译 (本章详谈的内容,js的执行过程会先对整体语法进行扫描,若存在逻辑错误或者语法错误,将会抛出错误,停止执行。否则,在变量声明和函数声明时,进行预编译。此时不进行赋值,也就是没有初始化行为。匿名函数,不参与预编译)

  3. 解释执行 (从上到下,解释一行,执行一行)

预编译

预编译分为两个部分,全局预编译与局部预编译

全局预编译,优先进行

  1. 创建GO对象(Global Object) 全局对象
  2. 查找变量名,作为GO对象的属性,初始化为undefined
  3. 查找函数声明,作为GO属性,将函数体作为值 (这一步,并不会执行函数体内的内容,所以函数体内,对于我们而言,依旧是未知领域)
   var run;
   console.log(run)
   run()
   function run(){
     console.log("run")
   }
   //1. 创建全局GO对象
   //2. 查找变量名,GO.run = undefined,变量声明提升
   //3. 查找函数声明,GO.run = function,函数声明提升
   // 预编译完成后,开始执行
   // 打印 function
   // 执行run 打印run
   // 反之如果将 var run -> var run = 1;则会抛出错误

遇到函数执行语句,开始对函数内的内容进行预编译。也就是局部预编译

局部预编译

  1. 创建AO对象(Activation Object)
  2. 寻找形参和变量声明,将形参名和变量作为AO属性名,赋值undefined
  3. 实参和形参相统一
  4. 函数体内,查找函数声明(函数嵌套函数)
function run(a, b) {
  var c = 1;
}
run (1,2)
// AO对象
// 形参 a,b  变量c
// 相统一 a=1 b=2
// 查找函数声明