关于js预编译的事

114 阅读3分钟

前言

JavaScript中存在预编译的过程,是为了确保代码在执行之前具有正确的执行环境和作用域。预编译阶段会对变量和函数进行声明和初始化,并建立作用域链,以便在代码执行阶段可以正确地访问和处理这些变量和函数。通过预编译阶段,JavaScript的代码在执行之前可以进行必要的准备工作,以确保变量和函数的正确性和可用性。这有助于提高代码的可靠性和执行效率。

首先我们来做一道题目,请问下面的这段代码会输出什么?

function a(a) {
   console.log(a);
    var a=456
    
}
a(1)

答案是1。我们再来看一道复杂一点的题目

var a;
function test(x) {
    console.log(a);       
    var a = 123;
    console.log(a);  
    function a() {}     
    console.log(a);       
    var b = function() {}
    console.log(b);       
}
console.log(a);
a=10
console.log(a);
test(1)

代码执行结果为

 undefined
 10
 [Function: a]
 123
 123
 [Function: b]

要想知道为什么,就要知道什么是预编译。接下来我给大家写一下这段代码的执行步骤。

两种预编译

首先,预编译分为全局预编译和函数体预编译。全局预编译发生在页面加载完成时执行,而函数预编译发生在函数执行的前一刻。

全局预编译可分为三步:

   1.创建GO对象(全称为Global Object)。
   2.找变量声明,赋值为undefined
   3.找函数声明,赋值为函数体
   

函数体预编译可分为四步:

  1.创建AO对象(全称为Activation Object2.找形参和变量声明,赋值为undefined
  3.将实参赋值给形参
  4.找函数声明,赋值为函数体
  

知道步骤之后,我们再来分析上面这道题目。

分析步骤

根据步骤,我们首先创建一个GO对象

 GO{
 
 }

然后找变量声明,赋值为undefined,并将变量作为GO的属性

GO{
 a:undefined
 }

再找函数声明,赋值为函数体,同样作为GO的属性(注意,如果此时变量名已经存在且与函数名同名,则GO中已存在的同名属性会被赋值成函数体)

GO{
  a:undefinedtest:function(){}//此处简写
   }

最后依次执行代码,所以第一个console.log(a)打印为undefined,之后执行a=10,第二个console.log(a);就打印的是10。

当执行到Test(a)时就开始函数体预编译了。

按照步骤,我们首先创建AO对象

AO{
x:undefined,
a:undefined
}

然后将实参赋值给形参

AO{
x:1,
a:undefined
}

再找函数声明

AO{
x:1,
a:function(){},//如上面所说,函数名与变量名相同则被覆盖
b:function(){}
}

最后依次执行代码,函数体内第一个console.log(a)打印为[Function: a],然后执行a=123,第二个和第三个console.log(a)打印都为123,最后一个打印为[Function: b]。

以上就是这一道题目的解题步骤,下面我们可以通过几道题目来巩固一下。

第一道

function test() {
    console.log(b);//undefined
    if (a) {
        var b = 100;
    }
    console.log(b);//undefined
    c = 234;
    console.log(c);//234
    }
    var a;
    test();
    a = 10;
    console.log(c);//234

第二道

var a = 10;
function foo() {
  console.log(a);//undefined
  if (true) {
    var a = 20;
  }
}
foo(); 
    

第三道

var x = 10;
function outer() {
  return function inner() {
    console.log(x);//20
  }
}
var innerFunc = outer();
x = 20;
innerFunc();

感谢您的观看,不足之处请指正!