四部曲:
-
首先创建一个AO对象 AO(Activation Object) 执行上下文
-
找形参和变量声明,将变量和形参名做为AO属性名,值为undefined
(第二步也叫变量声明提升)
-
将实参值和形参统一
-
在函数体里找函数声明,值赋予函数体
自己做了一个实验,例如:
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a () {}
console.log(a);
var b = function () {};
console.log(b);
}
fn(1);
解析:
//首先第一步: 创建了一个OA对象
OA{
}
//第二步:找形参和变量声明,将变量和形参名做为AO属性名,值为undefined
//此时a 和 b的值为undefined
OA{
a: undefined;
b: undefined;
}
//第三步:将实参值和形参统一
OA{
a:1;
b:undefined;
}
//第四步:在函数体里找函数声明,值赋予函数体
// 因为在函数体内, a 被函数声明了 所以 a 此时为 function(){}
OA{
a: function a (){};
b: undefined;
}
然后函数开始运行,
此时第一个console.log(a)打印的是 预编译已经编译好的OA里的a 所以打印的是 function a() {},
继续往下看 , a又被赋值了为123了
所以第二个console.log(a)打印的是123
继续往下看,此时的function a () {} 已经在预编译的时候被提升上去了
所以第三个 console.log(a) 打印的还是123
继续往下看 此时b被重新赋值了 function b () {} 所以
OA{
a: function(){};
b: function(){};
}
所以第四个console.log(b);打印的是function(){}