JS-预编译

242 阅读2分钟

首先要明确js执行步骤:

  1. 检查通篇的语法错误,有语法错误一行都不会执行
  2. 预编译
  3. 解释一行执行一行

暗示全局变量 imply global

在全局不管是声明变量也好,不声明变量也好,都会成为window对象的属性

var a = 1;
b = 2; //暗示全局变量
window = {
    a: 1,
    b: 2
}

函数内未声明的变量也是全局变量

function test() {
    var a = b = 1;
}
console.log(a, b) //报错
console.log(window.a, b) //undefined, 1 访问对象里不存在的属性不会报错,只会返回undefined

这个函数体的执行步骤:

  1. var a
  2. b = 1,挂载到全局GO
  3. a = b,局部AO里面没有b,往上去全局找b

预编译

AO(active object)活跃对象/函数上下文

  1. 创建AO对象
  2. 寻找函数的形参和变量声明,值为undefined
  3. 将实参的值赋值给形参
  4. 寻找函数声明,赋值函数体(不是函数表达式)
  5. 执行函数

GO(global object)全局上下文 == window

  1. 创建GO对象
  2. 找变量
  3. 找函数声明
  4. 执行

例1:

var b = 3;
console.log(a); //function a(a) {...}
function a(a) {
    console.log(a); //function a() {}
    var a = 2;
    console.log(a); //2
    function a() {};
    var b = 5;
    console.log(b); //5
}
a(1);
GO = {
    a: function a(a) {...}
    b: undefined -> 3
}
AO = {
    a: undefined -> 1 -> function a() {} -> 2
    b: undefined -> 5
}

例2:

a = 1;
function test() {
    console.log(a); //undefined,函数内有a,不会到全局里找,AO里的a也提升了
    a = 2;
    console.log(a); // 2
    var a = 3;
    console.log(a); //3
}
test();
var a
GO = {
    a: undefined -> a
}
AO = {
    a: undefined -> 2 -> 3
}

例3:

function test() {
    console.log(b); //undefined
    if(a) {
        var b = 2; //预编译的时候要放进去,因为预编译的时候不看语句,只看有没有变量声明
    }
    c = 3;
    console.log(c); //3
}
var a;
test(); //执行的时候a = undefined,所以函数里面的if语句不执行,b = undefined
a = 1;
console.log(a); //1
GO = {
    a: undefined
    test: function test() {}
    c: 3
}
AO = {
    b: undefined
}