了解预编译

62 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情

  • 预编译前奏

JavaScript执行三部曲:

  1. 语法分析:扫描全部js代码,看看有无语法错误,若有则一行都不执行
  2. 预编译
  3. 解释一行执行一行

函数预编译发生在函数执行的前一刻,全局的发生在全局执行的前一刻,所以GO比AO创建早

  • 函数预编译

/**
 * 函数预编译四部曲:
 * 1、创建AO对象(Active Object,块作用域,活跃对象)
 * 2、找形参和变量声明,将变量和形参作为AO的属性名,值为undefined
 * 3、将实参值与形参统一
 * 4、在函数体里找函数声明,值赋予函数体
 */

/**
 * 第二步:
 * AO {
 * a: undefined
 * b: undefined
 * }
 * 
 * 第三步:
 * AO {
 * a: 1
 * b: undefined
 * }
 * 
 * 第四步:
 * AO {
 * a: function a(){}
 * b: undefined
 * d: function d(){}
 * }
 */

function fn(a) {
    console.log(a); // function a(){}
    var a = 123; //变量声明已执行,只剩a=123赋值
    /**
     * AO{
     * a: 123
     * b: undefined
     * d: function d(){}
     * }
     */
    console.log(a); // 123
    function a() { }; // 预编译已看过,不用看
    console.log(a);  // 123
    var b = function () { }; // var b 预编译已看过,执行b = function(){}
    /**
     * AO{
     * a: 123
     * b: function(){}
     * d: function d(){}
     * }
     */
    console.log(b); // function(){}
    function d() { }; // 预编译看过了
}
fn(1);

全局预编译


/**
 * 全局预编译三部曲:
 * 1、创建GO对象(Global Object,Window,全局执行期上下文)
 * 2、找变量声明,将变量名作为GO的属性名,值为undefined
 * 3、找函数声明,值赋予函数体
 */



console.log(test);⑴

function test(test) {⑵

    console.log(test);⑶

    var test = 234;⑷

    console.log(test);⑸

    function test() { };⑹
}

test(1);⑺

var test = 123;⑻


解析:函数的预编译发生在函数执行的前一刻,全局的发生在全局执行的前一刻,所以GOAO创建的早,我们先来全局预编译:

全局预编译:

第二步:GO里有变量test

GO{

    test:undefined

}

第三步:函数声明有test,值赋予函数体

GO{

    test:function test(test) { console.log(test); var test = 234; console.log(test); function test() { }; }

}

全局执行:

第1行:输出test得function test(test){ console.log(test); var test = 234; console.log(test); function test() { }; }

第2行声明函数,整个函数体不看了

第7行:执行函数,就在执行函数的前一刻,AO对象产生了

第8行:执行test = 123
GO{

    test:123

}


函数预编译:当test执行的前一刻,A0就产生了。

第二步:形参变量都是test

AO{

    test:undefined

}

第三步:传参,test = 1

AO{

    test:1

}

第四步:函数声明有test

AO{

    test:function test() { }

}

函数执行:

第3行:输出test得function test(){ }(当AO里有这个属性值时就拿AO的属性值,没有的话他就会往上找,看看GO里有木有)

第4行: 执行test = 234

AO{

    test:234

}

第5行输出test得234,第6行跳过

最后输出结果:function test(test) { console.log(test); var test = 234; console.log(test); function test() { }; } function test() { } 234