至此,预编译环节结束,函数中变量按照AO对象中的值开始执行
function fn(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {};
console.log(a);
var b = function () {};
console.log(b);
function d() {};
}
fn(1);
以下都是伪代码,是我们肉眼看不见的
第一步: 词法分析有没有语法错误
第二步: 开始预编译
1、先创建一个全局对象GO
GO:{}
2、寻找变量声明,值设定为undefined,这个例子里面没有变量声明
GO:{}
3、寻找函数中的函数声明,将函数名作为GO属性名,值为函数体
GO:{
fn:function // 我们用function来代替函数体
}
4、GO寻找完了之后,开始寻找AO,先创建一个AO
AO:{}
5、寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined。用var声明的变量都是AO的属性名
AO:{
a: undefined, // 形参
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
}
6、将形参和实参相统一,即更改形参后的undefined为具体的形参值。
AO:{
a: 1, // 形参和实参相统一,fn(1),这里的实参是1
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
}
7、寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。
AO:{
a: function, // 发现了函数声明 function a() {};
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
d:function,// 发现了函数声明 function d() {};
}
这个时候其实相当于fn函数里面代码是这个样子的:
function fn(a) {
function a() {}; // 函数提升到上面
function d() {}; // 函数提升到上面
console.log(a);
var a = 123;
console.log(a);
console.log(a);
var b = function () {}; // 这个是变量声明,不是函数声明
console.log(b);
}
第三步: 代码解释执行
1、遇到第一个console.log(a); 这个时候看看AO里面的a的值是什么
AO:{
a: function, // 发现了函数声明 function a() {};
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
d:function,// 发现了函数声明 function d() {};
}
可以执行输出function a() {}
2、下一行var a = 123,给a赋值了,所以AO里面进行修改
AO:{
a: 123, // 给a赋值123
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
d:function,// 发现了函数声明 function d() {};
}
3、又遇到了console.log(a);
AO:{
a: 123, // 给a赋值123
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
d:function,// 发现了函数声明 function d() {};
}
这个时候看AO里面a的值已经是123了,所以输出123
4、下一行有function a() {}; 这个函数声明已经在预编译阶段就提升了,所以看下一行。
5、再次遇到了console.log(a);
AO:{
a: 123, // 给a赋值123
b: undefined, // 用var声明的变量,虽然给它赋值的是函数,但是它还是变量,不属于函数声明
d:function,// 发现了函数声明 function d() {};
}
这个时候没有对a作任何改变,所以依然输出123
6、 var b = function () {}; 这行对b做了一个赋值,赋值给它一个函数体,所以我们对AO进行修改
AO:{
a: 123, // 给a赋值123
b: function, // 赋值函数体 function () {}
d:function,// 发现了函数声明 function d() {};
}
7、console.log(b); 这个时候看看AO里面的b的值是什么
AO:{
a: 123, // 给a赋值123
b: function, // 赋值函数体 function () {}
d:function,// 发现了函数声明 function d() {};
}
可以看到是function,所以输出function () {}
后面几个例子可以自己试试,套用上面的步骤来操作
function test(a,b){
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b() {};
function d() {};
console.log(c);
}
test(1);
console.log(fun);
function fun(fun){
console.log(fun);
var fun = 234;
console.log(fun);
function fun () {};
}
fun(1);
var fun = 123
function demo(){
console.log(bb);
if (aa) {
var bb = 100;
}
console.log(bb);
cc = 234
console.log(cc);
}
var aa;
demo();
aa = 10;
console.log(cc);
a = 100;
function eg(e){
function a() {};
arguments[0] = 2;
console.log(e);
if (a) {
var b = 123;
var c = function(){}
}
var c;
a = 10;
var a;
console.log(b);
f = 123;
console.log(c);
console.log(a);
}
var a;
eg(1);
console.log(a);
console.log(f);