预编译
关JavaScript这门弱类型的动态语言我们都知道的是var声明的变量会声明提升,函数的声明也会整体提升。那为什么会存在这种声明呢?这就不得不提到JavaScript的预编译了,预编译就是在一段代码的执行之前编译器对代码会进行整理,使代码变成处理器能够读懂的样子。
预编译存在两种情况
-
预编译发生在函数体内时
-
预编译发生在全局时
1. 预编译发生在函数体内时
- 创建函数的AO对象(Action Object)
- 找形参和变量声明,将形参和变量声明作为AO的属性名,值赋予underfined
- 将实参和形参统一
- 在函数体内找函数声明,将函数名作为AO对象的属性名,将值赋予函数体
例如
function fn(){
console.log(global);//underfind
global=200;
console.log(global);//200
var global =300;
}
fn()
var global;
它的AO对象为:
AO={
global:undefined => 200 => 300
}
2. 预编译发生在全局
- 创建GO对象 (Global Objiect)
- 找变量声明,将变量名作为GO的属性名,值赋予underfined
- 在全局找函数声明,将函数名作为GO对象的函数名,将值赋予函数体
例如
function fn(){
console.log(global);//underfind
global=200;
console.log(global);//200
var global =300;
}
fn()
var global;
它的GO对象为
GO ={
global: underfind => 100
fn: function fn(){}
}
总结
当这段代码执行时,在第三行代码打印global的值时,首先先访问AO对象,此时发现AO对象中存在global且此时的global经过预编译它的值为underfind,所以第一个打印输出underfind。当执行到第二个打印时,global经过第三行代码的赋值操作变为了200,所以第二个打印输出的结果是200。
需要注意的是,在函数执行过程中在对变量进行查找时需先从AO对象中查找,如果AO对象中找不到这个变量才会到GO对象中去查找。