JS - 预编译

1,314 阅读2分钟

JS 代码的执行过程中,会先对整个代码的语法、语句进行扫描。若有语法、逻辑错误,报错并停止执行;若没有问题,则自上而下解释(翻译)一行执行一行。

  • 预编译分类:

    全局预编译 - GO (Global Object)

    局部预编译 - AO(Activation Object)

  • 预编译发生时间点:

    GO:页面加载(扫描)完成时

    AO:函数执行前一刻

  • 执行过程

    GO:全局预编译 - 全局执行上下文

    • 寻找变量声明

    • 寻找函数声明

    • 执行

    AO:局函预编译 - 函数执行上下文

    • 寻找函数体内的变量、形参
    • 实参 赋值 给形参
    • 寻找函数声声明
    • 执行

案例:

```
function a (val)  {
	var name = val
	function b () {}
}
var str = 'Hello World'
a(1)    
```

解释:

   GO 部分:
   1:全局扫描后 生产对应的GO (函数 a  、 变量 str )
   2:扫描解释后开始执行 ---> str 被赋值为:'Hello World' 
  	3:执行函数 a()
   GO: {
   	a(){}
       str: undefined ---> [ 开始执行后被赋值 ] -----> 'Hello World'
   }
   
   AO 部分:
   执行函数 a 的前一刻生成 a 函数的 AO
   a() -> AO 部分:
   1:寻找变量、形参 得到 name 、 val
   2:实参赋值给形参 val= 'Hello World'
   3:寻找函数声明 得到 b() {}
   4:执行(执行,变量 name 被赋值为 'Hello World')
   AO: {
   	name: undefined --->  [ 开始执行被赋值 ]  ----->  'Hello World'
   	val: undefined  ---> 'Hello World'
   	b(){}
   }
注意 :
* 预编译阶段发生变量声明、函数声明,但是并不赋值(因此存在变量提升)
* 只有在函数执行时才会生成当前函数的 AO 
* 匿名函数不参与 预编译流程,只有当执行到当前函数的时,才会变量初始化
* 当前函数执行结束,此函数的 AO 销毁,如果需要再次执行当前函数,会重新生成新的 AO 
* 函数中未定义的变量,默认将其定义在全局中 

函数中未定义的变量,默认将其定义在全局中:

function outer() {
	// console.log(b) // b is not defined 未走到 b = 2 不清楚当前的 b 是什么
	var a = 1
	b = 2
  	console.log(a) // 1
  	console.log(b) // 2
}
// console.log(a) // a is not  defined 未运行函数outer
// console.log(b) // b is not defined 未运行函数outer
outer()
console.log(a) // a is not  defined :a 是 outer() 中的变量,全局中无法找到(作用域的一个问题,后期再讨论)
console.log(b) // 2