Skip to content
On this page

预编译

变量提升

  • JS 在执行函数前,会先预编译,把用 var 声明的变量的声明提升到前面。

  • 只有一个语句 console.log(a),这样子会直接报错 a is not defined。

    js
    console.log(a); // a is not defined
    
  • 声明变量,但是不赋值,则会得到 undefined

    js
    var a;
    console.log(a); //undefined
    
  • 先打印,再声明变量 ( 执行代码前,会先进行一次预编译,把 var 变量的声明提升到前面。)

    js
    console.log(a); // undefined
    var a;
    

    代码等效于

    js
    var a;
    console.log(a);
    
  • 变量提升只会把变量的声明提升到前面,赋值则不会提升到前面。

    js
    console.log(a); // undefined
    var a = 123;
    console.log(a); // 123
    

    代码等效于

    js
    var a;
    console.log(a); // undefined
    a = 123;
    console.log(a); // 123
    

函数提升

  • 函数声明整体提升,函数调用不提升

    js
    console.log(test); // function test() {console.log(222)}
    test(); // 222
    console.log(111); // 111
    function test() {
      console.log(222);
    }
    

    等效于

    js
    function test() {
      console.log(222);
    }
    console.log(test);
    test();
    console.log(111);
    
  • 使用使用变量声明函数,则走的是变量提升路线,而不是函数声明路线

    js
    console.log(test); // undefined
    test(); // test is not a function
    var test = function () {
      console.log(111);
    };
    
  • 函数内部也会有变量提升,这时候会先预处理全局的,再预处理函数的,且函数内的变量、函数提升不能提升到函数外。

    js
    function mytest1() {
      console.log(a); // undefined
      b(); // 456
      var a = 123;
    
      function b() {
        console.log(456);
      }
    }
    
    mytest1();
    console.log(a); // a is not defined
    

    等效

    js
    function mytest1() {
      function b() {
        console.log(456);
      }
      var a;
    
      console.log(a);
      b();
    
      a = 123;
    }
    
    mytest1();
    console.log(a);
    
  • 隐式的全局变量 如果函数内部的变量没有定义,直接赋值,则会直接变成全局变量

    js
    function test() {
      a = 123;
    }
    
    test();
    console.log(a); // 123
    
    var a = 1;
    var b = 1;
    function func() {
      var a = 2;
      b = 2;
    }
    func();
    console.log(a); // 1
    console.log(b); // 2
    

预编译

全局预编译

  1. 创建 GO 对象(Global Object)
  2. 找变量声明,将变量作为 GO 属性(在浏览器中的话,实际上就是挂载到 window 对象上),值为 undefined
  3. 找函数声明,作为 GO 属性值为函数体

局部预编译

  1. 创建 AO 对象(Activation Object)
  2. 找形参和变量声明,将变量和形参作为 AO 属性,值为 undefined
  3. 实参和形参统一(将实参的值赋值给形参)
  4. 找函数声明,值赋予函数体

总结

  • GO 对象是全局预编译,所以它优先于 AO 对象所创建和执行。
  • 从结果上看是函数优先,但从过程来看是变量优先,因为变量提升后被之后的函数提升给覆盖掉了。

Released under the MIT License.