什么时候发生:
预编译发生在函数刚开始执行时(也可以说是执行前一刻)
预编译的4个步骤
- 生成执行期上下文对象,全局的执行期上下文对象是GO(Global Object),函数中生成函数的执行期上下文AO(Activation Object)
GO{//全局对象
属性1:,
属性2:
}
AO{//局部作用域对象
属性1:,
属性2:
}
- 将形参和变量声明提升,即将形参和变量的声明设置为AO的属性,值初始化为undefined
- 将实参赋值到AO对象中
- 函数声明设置为AO的属性,值为函数体(注意:函数表达式不是函数声明,而是变量声明)
访问变量时,遵循就近原则,即在函数内部访问时,优先访问当前作用域的属性,若没有,则向上查找
预编译过程举例练习:
//预编译过程:1.首先生成go对象,并放入属性,2.在函数执行之前,生成一个ao对象,放入函数作用域的属性
// GO{
// a:undefined,
// b:undefined,
// test:function test(a){
// //...
// }
// }
//GO对象生成好了,接下来执行语句
a = 10; //GO.a = 10
function test(a){
console.log(a);//打印6
console.log(b);//打印 function b(){}
var a = 100;
function b(){}
var c = function(){}//这里是函数表达式,不是函数声明
console.log(a);//打印100
console.log(c);//打印function(){}
}
var a;//声明已提升,执行时不会再执行该语句
//1.函数执行前生成一个AO对象
// AO{
// a:undefined,//2.形参与test函数内的a变量声明重名
// a:6,//3.实参赋值
// c:undefined,
// b:function b(){} //4.函数声明提升
// }
test(6);
var b = 20;
console.log(b);//打印20
注意:非严格模式下,所有未声明就赋值的变量,都是全局变量