JavaScript-预编译

什么是预编译?

预编译发生在函数作用域创建的阶段在函数执行之前。

函数、形参、变量的优先级别:
函数 > 形参 > 变量

全局作用域预编译

  1. 创建GO对象(Global Object)
  2. 查找变量声明,将变量名作为GO对象的属性名,只为 undefined
  3. 查找函数声明,值为函数体

函数作用域预编译

  1. 创建AO对象(Active Object)
  2. 查找函数形参以及函数内部的变量声明,形参名及变量名作为AO对象的属性,值为 undefined
  3. 实参和形参相统一,实参值赋给形参
  4. 查找函数声明,函数名作为AO对象的属性,如果函数名称和变量名称相同时会覆盖变量声明
1
function fn(a){
2
    console.log(a,1);  // ƒ a () {} 1
3
    var a = 2222;
4
    console.log(a,2); // 2222 2
5
    function a () {}
6
    console.log(a,3); // 2222 3
7
}
8
fn(1,2)

示例

1
function fn(a, c) {
2
    console.log(a);
3
    var a = 123;
4
    console.log(a);
5
    console.log(c);
6
    function a() { }
7
    if (false) {
8
        var d = 678
9
    }
10
    console.log(d);
11
    console.log(b);
12
    var b = function () { }
13
    console.log(b);
14
    function c() { }
15
    console.log(c);
16
}
17
18
fn(1, 2)

第一阶段:创建 AO 对象,查找函数形参以及函数内部的变量声明,实参和形参相统一,如果没有传递实参,那么值为 undefined

1
AO : {
2
    a : undefined -> 1
3
    c : undefined -> 2
4
    b : undefined
5
    d : undefined
6
}

第二阶段:查找函数声明

1
AO : {
2
    a : undefined -> 1 -> function a() { }
3
    c : undefined -> 2 -> function c() { }
4
    b : undefined -> function () { }
5
    d : undefined
6
}

执行代码

1
function fn(a, c) {
2
    console.log(a); // function a() { }
3
    var a = 123;
4
    console.log(a); // 123
5
    console.log(c); // function c() { }
6
    function a() { }
7
    if (false) {
8
        var d = 678
9
    }
10
    console.log(d); // undefined
11
    console.log(b); // undefined
12
    var b = function () { }
13
    console.log(b);  // function () { }
14
    function c() { }
15
    console.log(c); // function c() { }
16
}
17
18
fn(1, 2)