javascript 预解析
所谓预解析,既是函数执行的前一刻,js需要做的事情,函数的预解析分四步:
一、创建AO对象
二、寻找函数中的形参及变量声明,并把形参和变量的名作为AO对象的属性名,值为undefined
三、实参、形参相统一
四、寻找函数中的函数声明,并把函数名作为AO对象的属性名,函数整体赋值给该属性名,如果函数名与变量名重复,则把函数体直接赋值给变量
注意,以上为函数的预解析,如果是全局下执行某段js代码,它的预解析步骤与函数预解析步骤基本一致,差别有两点:
一、全局作用域下,创建的不是AO对象,是GO对象
二、全局作用域下,没有了第三步:实参、形参相统一
测试题:
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);
函数执行前 执行预解析
第一步:创建AO对象
AO {}
第二步:寻找函数中的形参及变量声明,并把形参和变量的名作为AO对象的属性名,值为undefined
AO { a:undefined, b: undefined }
注:形参和变量重名时,只写一个即可,即:写一个a即可
第三步:实参、形参相统一
AO {
a:1,
b: undefined
}
第四步:寻找函数中的函数声明,并把函数名作为AO对象的属性名,函数整体赋值给该属性名,如果函数名与变量名重复,则把函数体直接赋值给变量
AO{ a:function(){}, b:undefined, d:function(){} }
至此,js的预解析执行完毕,开始逐行执行代码
第一行:console.log(a); js到AO对象里找 a 所以 打印 function(){}
第二行:var a = 123; 因为预解析时 var a已被提升,所以这一行只是给a赋值,此刻AO对象里的a变为123;
AO{
a:123,
b:undefined,
d:function(){}
}
第三行:console.log(a); js到AO对象里找a 所以打印 123;
第四行:function a(){} 预解析时已提升,所以 忽略
第五行:console.log(a); js到AO对象里找a 所以打印 123;
第六行:var b = function(){} 因为预解析时 var b已被提升,所以这一行只是给b赋值,此刻AO对象里的b变为function(){};
AO{
a:123,
b:function(){},
d:function(){}
}
第七行:console.log(b); js到AO对象里找b 所以打印 function(){};
第八行:function d(){} 预解析时已提升,所以忽略
函数执行完毕!