在学习js的过程中,我们或多或少都会了解到:
var 声明的变量会存在声明提升
函数声明会整体提升
可是为什么它们会存在声明提升呢?不知你们有没有想过这个问题。
预编译
它们之所以会出现声明提升,正是因为有着预编译的作用,var声明的变量以及函数声明才会提升。
预编译的种类
预编译和变量声明一样,有着全局预编译和局部预编译(即函数预编译);全局预编译发生在页面加载完成时执行,而函数预编译发生在函数执行的前一刻。
全局预编译
全局预编译的步骤分为:
- 创建GO对象(Global Object)
- 找变量声明,将变量声明作为GO的属性名,值赋予undefined
- 在全局找函数声明,将函数名作为GO对象的属性名,值赋予函数体
让我们来看一下下面这段代码:
var global=100
function fn(){
console.log(global);
}
fn()
接下来我们按照前面的步骤来详细分析它的预编译的执行过程:
1.创建一个GO对象
GO ={
// 对象内容为空
}
2.找变量声明,并赋值为undefind
GO ={
global: undefind,
}
3.找函数声明,并赋值为函数体
GO ={
global: undefind,
fn: function fn(){}
}
4.按顺序执行代码,最后GO对象就变成了
GO ={
global: 100,
fn: function fn(){}
}
函数预编译
函数预编译的步骤分为:
- 创建函数的AO对象(Action Object)
- 找形参和变量声明,将形参和变量声明作为AO的属性名,值赋予undefined
- 将形参和实参统一
- 在函数体内找函数声明,将函数名作为AO对象的属性名,值赋予函数体
同样我将用下面一段代码来解释
function fn(a) {
console.log(a);
var a = 123
console.log(a);
function a() {}
console.log(a);
var b = function() {} //函数表达式
console.log(b);
function d() {}
var d = a
console.log(d);
}
fn(1)
接下来我按照前面的步骤来逐步分析它的预编译执行过程:
1.创建AO对象
AO ={
// 空对象
}
2.找形参和变量声明,将形参和变量声明作为AO的属性名,值赋予undefine
AO ={
a: undefined
b: undefined
d: undefined
}
3.将形参和实参统一
AO ={
a: 1
b: undefined
d: undefined
}
4.在函数体内找函数声明,将函数名作为AO对象的属性名,值赋予函数体
AO ={
a: function a(){}
b: function b(){}
d: function d(){}
函数按顺序执行代码,最终AO对象就变成了:
AO ={
a: 123
b: function b(){}
d: 123
结语
综上,在学习预编译时,我们要熟练的去掌握全局预编译和函数预编译的几个步骤,这样对于我们后面的进一步学习有着很大的作用。