JS的预编译原理

193 阅读1分钟

四部曲:

  • 首先创建一个AO对象 AO(Activation Object) 执行上下文

  • 找形参和变量声明,将变量和形参名做为AO属性名,值为undefined

    (第二步也叫变量声明提升)

  • 将实参值和形参统一

  • 在函数体里找函数声明,值赋予函数体

自己做了一个实验,例如:

function fn(a) {
    console.log(a);
    var a = 123;
    console.log(a);
    function a () {}
    console.log(a);
    var b  = function () {};
    console.log(b);
}
fn(1);

解析:

//首先第一步: 创建了一个OA对象 
OA{

}
//第二步:找形参和变量声明,将变量和形参名做为AO属性名,值为undefined
//此时ab的值为undefined
OA{
   a: undefined;
   b: undefined;
}
//第三步:将实参值和形参统一
OA{
    a:1;
    b:undefined;
}
//第四步:在函数体里找函数声明,值赋予函数体 
//  因为在函数体内, a 被函数声明了 所以 a 此时为 function(){}
OA{
    a: function a (){};
    b: undefined;
}

然后函数开始运行,
    此时第一个console.log(a)打印的是 预编译已经编译好的OA里的a 所以打印的是 function a() {},

继续往下看 , a又被赋值了为123了 

所以第二个console.log(a)打印的是123 

继续往下看,此时的function a () {} 已经在预编译的时候被提升上去了

所以第三个 console.log(a) 打印的还是123

继续往下看  此时b被重新赋值了 function b () {} 所以 
OA{
    a: function(){};
    b: function(){};
}

所以第四个console.log(b);打印的是function(){}