JS预编译那些事
JS的预编译可分为函数预编译和全局预编译这两种。
1、我们先看看函数预编译:
函数预编译可总结成以下几步:
- 预编译开始,会建立
AO(Activation Object)
对象 - 找形参和变量声明,使其作为
AO
的属性名,值赋予undefined
- 实参和形参相统一(即将实参值赋值给形参)
- 找函数声明,函数名作为
AO
属性名,值赋予函数体 - 按照代码执行顺序给对应的变量赋值
举个例子:
function fn(a){ var a = 3;
var b = 2; function a () {console.log('123')} var a= 6; } fn(5);
/**
上面的代码执行过程是这样的:
fn方法被调用的时候,
首先会建立AO对象,然后找到形参a和变量声明a以及b,值赋为undefined,
然后将实参5赋给形参a,再找到函数声明a,把函数体赋给函数声明a,这是a的值会覆盖之前的5(因为属性名相同),变为function a{};
代码正式执行时,又会把值3赋给变量a,这时a的值为3,把2赋给b,这时b的值为2;
再次往下执行,又会把值6赋给变量a,这时b的值为6;
*/
2、全局预编译因为没有形参和实参的概念,因此可以分为以下三步:
1、生成GO(Global Object)
2、找变量声明,由于全局变量默认挂载在window
之上,若window
当前已存在当前属性,忽略当前操作,若没有,变量作为属性名,值赋予undefined
。
3、找函数声明,函数与变量类似,先去window
上查看,不存在,函数作为函数名,值为函数体;
注意,let或者const声明的变量不是挂在window下,是挂在再Script下的;如下图
let a = 2; const b = 4; function fn(a){ var a = 3; function a () {console.log('123')} } fn(10)