js引擎主要做了三件事情
1.语法分析:就是检查代码有什么语法错误,如果没有则执行二
2.预编译:就是在内存中开辟一些空间,存放一些变量和函数
3.解释执行:执行代码
预编译的过程主要如下
1.创建AO对象
2.寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值为undefined。
3.将形参和实参相统一,也就是将实参的值赋值给形参
4.寻找函数中的函数声明,将函数名作为AO对象的属性名,值为函数体
需要注意几点的是:
1.如果函数是以变量的形式进行定义的,这种情况将不能进行函数提升,而仅仅是进行变量提升,也就是说AO对象里面的a的值为undefined
let a = function(){}
2.如果遇到函数名与变量名相同的情况,根据上面的顺序,函数名会覆盖掉变量名的。
像下面的代码中
function test (a) {
console.log(a);
var a = 2;
console.log(a);
function a() {
console.log(3)
}
console.log(b);
function b() {
console.log(4)
}
console.log(b);
console.log(c);
var c = function () {
}
console.log(c);
}
test(1);
首先创建AO对象(active object,也是GO global object)
AO{
}
然后寻找函数的形参和变量的声明,并且添加到AO中
AO{
a:undefined,
c:undefined,
}
再者是将形参和实参相统一
AO{
a:1,
c:undefined
}
寻找函数声明
AO{
a:function () {
console.log(3)
},
c:undefined,
b:function(){ console.log(4)}
}
然后开始逐行执行
function test (a) {
console.log(a);//function(){console.log(3)}
var a = 2;
console.log(a);//此时重新给a赋值,所以此时输出2
function a() {//不执行
console.log(3)
}
console.log(b);//function(){console.log(4)}
function b() {
console.log(4)
}
console.log(b);//function(){console.log(4)}
console.log(c);//undefined
var c = function () {
}
console.log(c);//function(){}
}
函数执行完毕,销毁AO对象
除此之外,预编译发生在什么时候呢?
因为js是解释性语言,也就是编译一句,执行一句
所以预编译发生在函数执行的前一刻内。