美文网首页让前端飞
作用域和预编译

作用域和预编译

作者: DARKSIIIDE | 来源:发表于2019-02-03 00:25 被阅读2次

    一、作用域初探

    function test() {
        var a = 123;
    }
    function demo() {
        var b = 234;
        document.write(a);
    }
    

    两个相邻的作用域
    互相不可以访问变量
    demo里不可以访问test里的a

    function test() {
        var a = 123;
        document.write(b);
        function demo() {
            var b = 234;
            document.write(a);
        }
    }
    

    两个嵌套的作用域
    外层的不可以访问里层的变量
    里层的可以访问外层的变量

    二、JS运行三部曲

    1.语法分析 即通篇扫描一遍看有没有语法错误
    2.预编译
    3.解释执行

    三、预编译

    1.预编译中的提前规则

    (1)举例

    function test() {
        console.log('a');
    }
    test();
    
    test();
    function test() {
        console.log('a');
    }
    

    均可打印a

    var a = 123;
    console.log(a);
    

    输出123

    console.log(a);
    var a = 123;
    

    输出undefined

    console.log(a);
    

    报错 变量未声明

    (2)规则

    a. 函数声明 整体提升

    函数不管声明在哪系统都会把他提升到逻辑的最前面

    b. 变量 声明提升

    var a = 123;              变量声明并赋值
    系统把语句拆成        var a; 声明变量
                                     a =123; 变量赋值
    然后把声明语句放在逻辑最前面
    赋值语句不动
    所以输出undefined未赋值而不报错

    2.预编译前奏

    (1)inply global 暗示全局变量
    即任何变量,如果变量未经声明就赋值,此变量就为全局对象window所有。


    eg:a = 123; 不报错
    a = 123; ===> window.a = 123;


    (2)一切声明的全局变量,全是window的属性


    eg:var b = 123; ===> window.b = 123;


    (3)window就是全局的域
    var a = 123;=====>window { a : 123 ; }
    在全局上访问 a 就是访问 window.a

    function test() {
        var a  =  b = 123;
        // 连续赋值
        // 1.b = 123     先把123赋值给未声明的b
        // 2.var a;      再声明a
        // 3.a = b;      把b赋给a
    }
    test();
    

    访问 window.a 打印undefined
    访问 window.b 打印123

    3.函数体系的预编译

    1111111.预编译发生在函数执行的前一刻

    eg

    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 () {}
    }
    fn(1);
    

    过程分析及总结
    (1)创建AO对象 Activation Object(作用域 执行期上下文)

    AO{}
    

    (2)找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

    AO{
        a : undefined,
        b : undefined,
    }
    

    (3)将实参值和形参统一

    AO{
        a : 1,
        b : undefined,
    }
    

    (4)在函数体里面找函数声明,值赋予函数体

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

    2222222.从AO域里取东西执行函数及过程

            function fn(a) {
                console.log(a);             打印 function a () {}
    
                var a = 123;                var a;预编译时被提升不用再看
                                            执行 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);
    

    打印结果:
    function a () {}
    123
    123
    function () {}

    4.全局预编译

    全局预编译发生在全局执行的前一刻
    所以先生成GO再生成AO

    console.log(a)
    
    var a = 123;
    function a() {}
    

    全局预编译 打印function a() {}


    GO {
    a : undefined,
    }


    var a = 123;
    funcation a () {}
    

    GO {
    a : funcation () {},
    }


    GO 就是 window
    即为任何全局变量都是window上的属性

    eg1:题 + 执行顺序

    (1) 生成GO对象 GO{}(global object) 这个GO就是window

    GO{}
    

    (2)将全局的变量声明(的名)储存一GO对象中,value为undefinde

    GO{
        test : undefined
    }
    

    (3) 将全局的函数声明的函数名作为GO对象中的key,函数整体内容为value储存到go对象中

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

    (4)执行函数前创建AO

    AO变化过程
    AO{
        test : undefined,
    }
    AO{
        test : 1,
    }
    AO{
        test : function () {},
    }
    AO{
        test : 234,
    }
    

    (5)执行函数

    test(1);
    var test = 123;
    

    eg2:题 + 执行顺序

    (1)GO{
        a : 10,
        c : 234
     }
    (2)function test () {
        console.log(b); // 输出结果undefined
        if(a) {
            var b = 100;
        }
        console.log(b); // 输出结果undefined
        c = 234;
        console.log(c); // 输出结果234
    }
    var a;
    AO{
        b : undefined,
    }
    a = 10;
    test();
    console.log(c); // 输出结果234
    

    最终输出:
    undefined
    undefined
    234
    234

    相关文章

      网友评论

        本文标题:作用域和预编译

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