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