预编译

预编译是指在程序运行之前,先对程序进行一些处理,例如预处理、编译、链接等,以便提高程序运行效率和减少运行时的错误。

编译的作用:提高程序的效率和稳定性,减少程序在运行过程中可能出现的错误,并提高程序的可维护性可扩展性

作用域

作用域是函数身上的属性 [[scope]](给js引擎访问的,我们拿不到 — 隐式属性),用于存储函数中的有效标识符

作用域链

作用域是执行期上下文对象的集合,这种集合呈链式连接,我们把这种链关系称之为作用域链。

  • GO (Global Object):函数执行上下文对象;
  • AO (Activation Object):全局执行上下文对象;(可访问GO)

代码

 1function a() {
 2   function b(){
 3    var b = 22
 4    console.log(a)
 5   }
 6   var a = 111
 7   b()
 8  
 9}
10
11var glob = 100
12a()

作用域链

分析

全局定义了函数a和global,形成如图GO,此时a[[scope]]的0指向GO,函数a内定义了函数b和a,形成如图AO,此时a[[scope]]的0指向自己的AO,1指向GO,函数b定义了b,形成如图AO,b[[scope]]的0指向自己的AO,1指向a[[scope]]。

声明提升

  • 变量声明,声明提升(上一篇文章提到过)
  • 函数声明,整体提升
 1test()
 2function test() {
 3    var a = 123
 4    console.log(a)
 5}

上述代码相当于:

 1
 2function test() {
 3    var a = 123;
 4    console.log(a);
 5}
 6test();

预编译的分析(重点!)

定义

  • 发生在全局:
  1. 创建GO对象
  2. 找变量声明,将变量名作为GO的属性名,值为undefined
  3. 在全局找函数声明,将函数名作为GO的属性名,值为该函数体
  • 发生在函数体内:
  1. 创建一个AO对象
  2. 找形参和变量声明,将形参和变量名作为AO的属性名,值为undefined
  3. 形参和实参统一
  4. 在函数体内找函数声明,将函数名作为AO的属性名,值为该函数体

步骤

全局预编译—>GO—>执行,碰见函数—>函数预编译—>AO—>执行函数

实例一

代码

 1var a = 1
 2function fn(a) {
 3    var a = 2
 4    function a() {}
 5    console.log(a)
 6}
 7
 8fn(3)

分析

  • 首先进行全局预编译—>GO
  1. GO:{ }
  2. GO:{ a:undefined }
  3. GO:{ a:undefined , fn:function(a){ var a = 2; function a() {}; console.log(a); }
  • 执行
  1. GO:{ }
  2. GO:{ a:1 }
  3. GO:{ a:undefined , fn:function(a){ var a = 2; function a() {}; console.log(a); }
  • 碰见函数,进行函数预编译—>AO
  1. AO:{ }
  2. AO:{ a:undefined;(这里是a:undefined;(形参)a:undefined;(变量)) }
  3. AO:{ a:3(fn(3)), }
  4. AO:{ a:function(){}, (a:3;a:function(){};最后得出的结果) }
  • 执行函数

    AO:{ a:2, }

实例二

代码

 1function fn() {
 2    console.log(a);
 3    var a = 123;
 4    console.log(a);
 5    function a() {};
 6    console.log(a);
 7    var b = function(){};
 8    console.log(b);
 9    function c(){};
10    var c = a;
11    console.log(c);
12}
13
14fn(1);

分析

 1GO:{
 2    fn:function fn(){}
 3}
 4
 5AO:{
 6    a:undefined-->undefined-->1-->function a(){},  -->123,
 7    b:undefined,  -->function b(){},
 8    c:undefined-->function c(){},  -->123
 9

实例三

代码

 1function test(a, b) {
 2    console.log(a);
 3    c = 0
 4    var c;
 5    a = 3
 6    b = 2
 7    console.log(b);
 8    function b() {}
 9    console.log(b);
10  }
11  test(1)

分析

 1GO:{
 2    test:function
 3}
 4
 5AO:{
 6    a:undefined-->1,  -->3
 7    b:undefined-->undefined-->function b(){},  -->2
 8    c:undefined, -->0
 9    
10}
个人笔记记录 2021 ~ 2025