通常预编译被简单概括为函数声明整体提升和变量声明提升
函数的定义回顾
首先回顾函数的常用的两种定义方法
- 函数声明
function test() {
...
}
- 函数表达式
var test = function() {
...
};
函数预编译四部曲
函数预编译发生在函数执行的前一刻
- 创建AO对象 Activation Object(执行期上下文)
- 找形参和变量声明,将形参和变量声明作为AO对象属性名,值为undefined
- 将实参的值赋给形参
- 在函数体中找到函数声明,属性名为函数名,属性值为函数体
实例
function test(a, b) {
console.log(a);
console.log(b);
c = 0;
var c;
a = 3;
b = 2;
function b(){}
function d(){}
console.log(b);
}
test(1);
按照四部曲分析
1.创建AO对象
AO {
}
2.找形参和变量声明,将形参和变量声明作为AO对象属性名,值为undefined
AO {
a: undefined,
b: undefined,
c: undefined
}
3.将实参的值赋给形参
AO {
a: 1,
b: undefined,
c: undefined
}
4.在函数体中找到函数声明,属性名为函数名,属性值为函数体
AO {
a: 1,
b: function b() {},
c: undefined,
d: function d() {}
}
接下来按顺序执行语句
function test(a, b) {
console.log(a); //1
console.log(b); //function b
c = 0;
a = 3;
b = 2;
console.log(b); //2
}
test(1);
全局预编译
全局预编译与函数预编译差别不大,发生在执行全局前
- 创建GO对象:执行期上下文(Global Object)
- 寻找变量声明,并且当做属性放在GO对象里,值为undefined
- 寻找函数声明,值赋予函数体
实例
console.log(test);
function test(test) {
console.log(test);
var test = 234;
console.log(test);
function test () {
}
}
test(1);
var test = 123;
执行全局前,开始全局预编译
1. 创建GO对象
GO {
}
2. 寻找变量声明,并且当做属性放在GO对象里,值为undefined
GO {
test: undefined、
}
3. 寻找函数声明,值赋予函数体
GO {
test: function test(test) {
...
}
}
执行语句
console.log(test);// function test(test) {...}
function test(test) {
console.log(test);
var test = 234;
console.log(test);
function test () {
}
}
test(1);
test = 123;
执行函数前发生函数预编译
1.创建AO对象
AO {
}
2.找形参和变量声明,将形参和变量声明作为AO对象属性名,值为undefined
AO {
test: undefined
}
3.将实参的值赋给形参
AO {
test: 1
}
4.在函数体中找到函数声明,属性名为函数名,属性值为函数体
AO {
test: function test () {}
}
执行函数
function test(test) {
console.log(test); // function test () {}
test = 234;
console.log(test); // 234
function test () {
}
}
两道面试题
面试题1
function bar() {
return foo;
foo = 10;
function foo() {
}
var foo = 11;
}
console.log(bar());
分析
//GO {
// bar : function bar() {},
//}
function bar() {
return foo;
foo = 10;
function foo() {
}
var foo = 11;
}
//AO {
// foo: undefined => function foo() {},
//}
console.log(bar());//function foo() {}
面试题2
console.log(bar());
function bar() {
foo = 10;
function foo() {
}
var foo = 11;
return foo;
}
分析
//GO {
// bar: function bar() {},
//}
//AO {
// foo: undefined => function foo(){} => 10 => 11
//}
console.log(bar()); //11
function bar() {
foo = 10;
function foo() {
}
var foo = 11;
return foo;
}