美文网首页
JavaScript预编译和变量提升

JavaScript预编译和变量提升

作者: 椰果粒 | 来源:发表于2019-03-15 16:43 被阅读0次

    JavaScript是解释型语言,会先预编译,然后执行,在执行过程中顺序执行。
    因此在JS中存在变量提升的现象

    在函数中预编译执行步骤:

    • 创建空AO对象,(Activity Object)执行期上下文
    • 寻找函数的形参变量声明,将变量和形参作为AO对象的属性名,值为undefined
    • 将形参和实参相统一,将undefined更改为具体实参值。
    • 寻找函数中的函数声明,将函数名作为AO属性名,值为函数体
    • 预编译环节结束
    • 执行,不断更新AO对象
    • 执行完毕,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(){}
    }
    
    1. 创建空AO对象
    AO{
      // 空对象
    }
    
    1. 寻找函数形参和变量声明
    AO{
      a: undefined,
      b: undefined,
    }
    
    1. 将形参和实参相统一
    AO{
      a: 1,
      b: undefined
    }
    
    1. 函数声明
    AO{
      a: function a(){},
      b: undefined,
      d: function d(){},
    }
    

    预编译环节结束,AO对象更新为

    AO{
      a: function a(){},
      b: undefined,
      d: function d(){},
    }
    

    函数开始顺序执行

    function fn(a){
      console.log(a); // function a(){}
      var a = 123     // 对a赋值,AO对象改变
      console.log(a)  // 123
      function a(){}  // 预编译环节进行变量提升,执行时不看此行代码
      console.log(a)  // 123
      var b = function(){}  // 函数声明,对b重新赋值,AO对象改变
      console.log(b)   // function b(){}
      function d(){}  // 预编译环节变量提升,执行时不再看此行代码
    }
    

    实例二

    function test(a,b){
      console.log(a); // 1
      c = 0;          // AO更新
      var c;          // 预编译,不看
      a = 3;          // AO更新
      b = 2;          // AO更新
      console.log(b); // 2
      function b(){}; // 预编译,不看
      function d(){}; // 预编译,不看
      console.log(b); // 2
    } 
    test(1); // 1 2 2
    /**
    AO1{}
    AO2{
      a: undefined,
      b: undefined,
      c: undefined,
    }
    AO3{
      a: 1,
      b: undefined,
      c: undefined,
    }
    AO4{
      a: 1,
      b: function a(){},
      c: undefined,
      d: function c(){},
    }
    end;
    **/
    

    实例三

    // 引入GO(全局对象)
    console.log(test);    // function test(test){,,,,,}
    function test(test){
      console.log(test);  // function test(){}
      var test = 234;     // AO改变
      console.log(test);  // 234
      function test(){}   // 预编译,不看
    }
    test(1);
    var test = 123;
    
    执行结果:
    // function test(test){,,,,,}
    // function test(){}
    // 234
    
    解析过程:
    /**
    页面加载完成,生成GO对象 
    GO1{
      test: undefined
    }
    GO2{
      test: function(test){xxxxx}
    }
    执行test()钱生成AO对象
    AO1{
      test: undefined,
    }
    AO2{
      test: 1
    }
    AO3{
      test: function test(){}
    }
    预编译结束,开始执行
    AO4{
      test: 234
    }
    **/
    

    实例四

    function demo(){
      console.log(b);  // undefined
      if(a){
        var b = 100;
      }
      console.log(b);  // undefined
      c = 234;         // 全局变量
      console.log(c);  // 234
    }
    var a;
    demo();
    a = 10;
    console.logs(c);   // 234
    
    // undefined undefined 234 234
    
    /* 
    GO1{
      a: undefined
    }
    GO2{
      a: undefined,
      demo: function demo(){xxxxx},
    }
    执行demo函数前预编译,由于c未声明就使用,所以是全局变量
    GO2{
      a: undefined,
      demo: function demo(){xxxxx},
      c: undefined
    }
    a是undefined,if里不执行
    输出undefined
    GO4{
        a : undefined,
        demo : function demo(){}
        c : 234;
    }
    //输出234
    GO5{
        a : 10,
        demo : function demo(){}
        c : 234;
    }
    //输出234
    */
    

    本文参考https://juejin.im/post/5aa6693df265da23884cb571

    相关文章

      网友评论

          本文标题:JavaScript预编译和变量提升

          本文链接:https://www.haomeiwen.com/subject/usrrmqtx.html