【JavaScript】预编译

本文详细解释了JavaScript中的全局预编译和函数预编译过程,涉及GO和AO对象的创建、变量和函数声明处理,以及变量提升现象。通过实例展示了预编译如何影响代码执行和最终结果。
摘要由CSDN通过智能技术生成

预编译在什么时候发生

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

全局预编译的步骤

  1. 创建GO(Global Object,全局执行期上下文,在浏览器中为window)对象;
  2. 寻找var变量声明,并赋值为undefined;
  3. 寻找function函数声明,并赋值为函数体;
  4. 执行代码。
案例

我们先来看一下下面这段代码:

var x = 1,
    y = z = 0;

function add (n) {
  return n = n + 1;
}

y = add(x);
function add (n) {
  return n = n + 3;
}

z = add(x)

接下来我们来按照前面的步骤详细分析它的预编译执行过程:
1.创建一个GO对象

GO{
    // 对象内容为空
}
  1. 寻找var变量声明,并赋值为undefined
Go{
    x: undefined
    y: undefined
    z: undefined
}
  1. 寻找function函数声明,并赋值为函数体
GO{
   x: undefined
   y: undefined
   z: undefined
   add: function add (n) { return n = n + 1; } => function add (n) { return n = n + 3; }
}
  1. 按顺序执行代码
var x = 1,
    y = z = 0;

function add (n) {
  return n = n + 1;
} //预编译环节已经进行了变量提升,故执行时不在看这行代码

y = add(x);
function add (n) {
  return n = n + 3;
}//预编译环节已经进行了变量提升,故执行时不在看这行代码,但是这一函数覆盖了前面的add函数

z = add(x)

故而我们的GO对象变成了

GO{
   x: 1
   y: 0
   z: 0
   add: function add (n) { return n = n + 3; }
}

所以我们可以知道,此时x的值为1,y的值为4,z的值为4

函数预编译的步骤

  1. 创建AO对象,执行期上下文(后面更新关于执行期上下文详解)。
  2. 寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
  3. 将形参和实参相统一,即更改形参后的undefined为具体的形参值。
  4. 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。
一个小案例
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);

接下来我们来按照前面的步骤详细分析它的预编译执行过程:

  1. 创建AO对象
AO{
    // 空对象
}
  1. 寻找函数的形参和变量声明,将变量和形参名作为AO对象的属性名,值设定为undefined.
AO{
    a: undefined,
    b: undefined
}
  1. 将实参赋值给形参
AO{
    a: 1,
    b: undefined
}
  1. 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体。
AO{
    a: function(){}
    b: undefined
    d: function(){}
}

函数开始逐行顺序执行:

function fn(a){
    console.log(a);// 输出functiona(){}
    var a = 123;
    console.log(a);// 输出123
    
    function a(){};//预编译环节已经进行了变量提升,故执行时不在看这行代码
    console.log(a);// 输出123
    
    var b = function(){};//这个是函数表达式不是函数声明,故不能提升,会对AO中的b重新赋值
    console.log(b);//输出function(){}
    
    function d(){};
 }

结果在代码块的注释里

一个综合案例

var a = 1;
console.log(a);
function test(a) {
  console.log(a);
  var a = 123;
  console.log(a);
  function a() {}
  console.log(a);
  var b = function() {}
  console.log(b);
  function d() {}
}
var c = function (){
console.log("I at C function");
}
console.log(c);
test(2);
  1. 全局预编译
GO{
    a: undefined,
    c: undefinedtest: function(a) {
        console.log(a);
        var a = 123;
        console.log(a);
        function a() {}
        console.log(a);
        var b = function() {}
        console.log(b);
        function d() {}
    }
}
  1. 按顺序执行代码
GO{
    a: 1,
    c: function (){
        console.log("I at C function");
    }test: function(a) {
        console.log(a);
        var a = 123;
        console.log(a);
        function a() {}
        console.log(a);
        var b = function() {}
        console.log(b);
        function d() {}
    }
}
  1. 执行到test(2),函数开始预编译
  • 3.1
AO{
    a: undefined,
    b: undefined
}
  • 3.2
AO{
    a: 2,
    b: undefined
}
  • 3.3
AO{
    a: function(){},
    b: undefined,
    d: function(){}
}
  1. 执行结果
var a = 1;
console.log(a); // 1
function test(a) {
  console.log(a); // function a() {}
  var a = 123;
  console.log(a); // 123
  function a() {}
  console.log(a); // 123
  var b = function() {}
  console.log(b); // function b() {}
  function d() {}
}
var c = function (){
console.log("I at C function");
}
console.log(c); // function c(){ console.log("I at C function"); }
test(2);

总结

以后遇到关于预编译的相关问题,大家就可以按照上面的步骤进行解决了,还有就是如果大家在遇到的代码里有if语句的话,在预编译阶段先无视他就可。希望这篇文章能够帮助到和我一样迷惑的你!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jerry_ww

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值