首先,预编译有四个步骤:
- 创建AO对象
- 找形参和变量声明,将变量声明和形参名作为AO属性名,值为undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体
以下代码我们来详细解读是如何进行预编译
function fn(a){
console.log(a)
var a = 123
console.log(a)
function a(){}
console.log(a)
var b = function b(){}
console.log(b)
function d(){}
}
fn(1)
- 首先遇到函数fn(1),进入到函数fn内,创建AO对象
- 在函数体内,找形参和变量声明,将变量声明和形参名作为AO属性名,值为undefined
AO:{
a:underfind,
b:underfind,
d:underfind
}
- 将实参值和形参统一
AO:{
a:1,
b:underfind,
d:underfind
}
4.在函数体里面找函数声明,值赋予函数体
AO:{
a:function a(){},
b:underfind,
d:function d(){}
}
然后依次执行函数体内的语句 遇到console.log(),打印函数function a(){},遇到var a = 123,将a赋值123,又遇到console.log(),打印123,遇到 var b = function b(){},将b赋值function b(),遇到console.log(),将函数打印出来,执行完毕。
再举个例子:
global = 100
function fn(){
console.log(global)
global = 200
console.log(global)
var global = 300
}
fn()
var global
遇到global = 100,在全局中定义一个GO,赋值underfind,变量声明提升,所以即使没有var一个global,后面var了也能生效,遇到fn函数,进入到fn函数体内,并创建一个AO,将函数体内的global赋值underfind,然后按顺序执行,打印fn内的第一个global为underfind,第二个为200,因为在执行函数的时候,会优先找函数内部的global,如果没有,才会去上级找。