先创建GO对象(Global Object),再创建AO对象(Activation Object)。
GO(Global Object)
GO:先不看函数内部的代码
1、创建GO对象;
2、找变量声明,将 变量 作为GO属性名,值为undefined;
3、再找 函数声明,值赋予函数体;
函数预编译,开始创建AO对象(预编译发生在函数执行的前一刻)
AO(activation object )
全称:活跃对象/执行期上下文,在函数执行前执行函数预编译,此时会产生一个AO对象,AO对象保存该函数的参数变量。
函数预编译步骤:
产生AO对象
将函数的形参和函数内声明的变量当作AO对象的属性名,值全为undefined。变量的赋值在原先的位置
将实参赋值给形参属性
在函数内声明的函数,函数名作为OA的属性名,函数体赋值给值。(若函数名和变量重名,函数体会覆盖原先的变量值)
(function(a){
console.log(a);
var a = 12;
console.log(a);
function a(){...}
console.log(a);
var b = function(){...}
console.log(b);
function d(){...}
})(1);
1.首先创建一个GO对象,和AO对象
(立即执行函数是在全局作用域中执行的,立即执行函数执行时创建AO对象)
GO{
AO{
}
}
2.找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
变量声明找到了a和b,其实形参也是一种变量声明,类似于function(a,b){var a,b;},这里的形参和函数里的变量声明a重名了,那么后一个变量声明会被忽略…
GO{
AO{
a: undefined,
b: undefined
}
}
3.将实参和形参统一
(实参值赋值给形参)
GO{
AO{
a: 1,
b: undefined
}
}
4.在函数体里面找函数声明,值赋予函数体
(变量声明在前,函数声明在后。所以变量声明提升和函数声明提升会出现一个先后顺序)
GO{
AO{
a: function(){...},
b: undefined,
d: function(){...}
}
}
预编译过程结束。
然后开始执行:
1.执行第一行:输出function(){…}
2.执行第二行赋值:
GO{
AO{
a: 12,
b: undefined,
d: function(){...}
}
}
3.执行第三行:输出12
4.第四行是函数声明,预编译已经执行了,跳过,执行第五行,输出:12
5.执行第六行赋值:
GO{
AO{
a: 12,
b: function(){...},
d: function(){...}
}
}
6.执行第七行:输出:function(){…}
7.第八行是函数声明,跳过,执行完成…接下来销毁AO,再销毁GO