美文网首页
JavaScript作用域和预解析

JavaScript作用域和预解析

作者: AuglyXu | 来源:发表于2018-11-03 18:43 被阅读0次

    作用域链

    • 默认情况下全局作用域, 我们称之为0级作用域

    • 只要定义一个函数就会再开启一个作用域

    • 如果该函数是在全局作用域中定义的, 那么函数的作用域我们称之为1级作用域

    • 如果该函数是在其他函数中定义的, 那么作用域级数为所在函数+1级作用域

    • 作用域链的作用:

      • 当前变量如果在自己的作用域内找不到,就会到上级作用域内寻找
     // num属于0级作用域
        var num = 123;
        // test函数也属于0级作用域
        function test() {
            // test的{}中是新开启的一个作用域
            // test的{}中定义的变量和函数都属于1级作用域
            // value属于1级作用域
            var value = 666; // 1级作用域
            // demo函数也属于级作用域
            function demo() {
                // demo的{}中是新开启的一个作用域
                // demo的{}中定义的变量和函数都属于2级作用域
                // temp属于2级作用域
                var temp = 678;
                console.log(temp);
            }
        }
    

    全局变量

    • 默认情况下在一对script标签或者在一个单独的JS文件中定义的变量都是全局变量
    • 默认情况下在函数中定义的变量都是局部变量
    • 注意点:
      • 但是如果在函数中定义变量时, 没有书写var关键字, 那么这个局部变量就会变为全局变量
      • 虽然这样可以将一个局部变量变为全局变量, 但是在企业开发中千万不要这样写

    预解析

    • 将变量和函数的声明提升到当前作用域的最前面, 这个我们就称之为预解析
    • 注意点:函数的声明不只是function 函数名() 而是整个函数
    • 预解析之后的代码
      1. 声明提前的代码
      2. 自己编写的代码
    • 有多级作用域的代码解析方法
      • 从0级作用域开始依次预解析
    源代码
     var num = 123;
        fun();//undefined
        function fun() {
            console.log(num);
            var num = 666;
        }
    
    预解析之后的代码
    var num;
    function fun(){
      var num;
      console.log(num)
      num = 666;
    }
    num = 123;
    fun();
    
    源代码
    var a = 666;
    test();
    function test() {
        var b = 777;
        console.log(a);
        console.log(b);
        var a = 888;
    }
    
    预解析的代码
    var a;
    function test() {
        var b;
        var a;
        b = 777;
        console.log(a); // undefined
        console.log(b); // 777
        a = 888;
    }
    a = 666;
    test();
    

    • 预解析注意点:
      • 变量和函数同名时, 函数的优先级高
    • 注意点:
      • 在企业开发中变量的名称千万不要和函数的名称一样, 否则会出现混乱问题
    • 规则:
      • 如果在同名的变量和函数声明之前访问这个名称, 拿到的是函数
      • 如果在同名的变量和函数声明之后访问这个名称, 拿到的是变量
        console.log(value); // function value() {}
        var value = 123;
        function value() {
            console.log("fn value");
        }
        console.log(value); // 123
    

    不同函数定义方式的区别

    • 在高级别的浏览器中, 预解析不会提升{}中的函数
    • 但是在低级别的浏览器中, 预解析会提升{}中的函数
    源代码
    if(true){
        // 前面我们说过默认都是0级作用域, 也就是全局作用域
        // 只有定义了函数才会开启一个新的作用域
        // 所以test函数虽然定义在了if的{}中, 但是并没有定义在其它函数中
        // 所以test函数还是属于0级作用域, 所以还是一个全局函数
        function test() {
            console.log("test1");
        }
    }else{
        function test() {
            console.log("test2222222");
        }
    }
    test();
    
    高级别不会提升
    
    低级别浏览器提升后的代码
    function test() {
        console.log("test1");
    }
    function test() {
        console.log("test2222222");
    }
    if(true){
    }else{
    }
    test();
    
    • 所以在高级别浏览器中,test()会打印test1,但在低级别了浏览器中会打印test2222222
    • 为了解决如上问题,我们可以用函数表达式的方式将函数保存在变量中
     if(false){
            var test = function () {
                console.log("test1");
            }
        }else{
            var test = function () {
                console.log("test22222");
            }
        }
        test();
    
     高级别或者低级别提升后的代码
        var test;
        if(true){
            test = function () {
                console.log("test1");
            }
        }else{
            test = function () {
                console.log("test22222");
            }
        }
        test();
    

    相关文章

      网友评论

          本文标题:JavaScript作用域和预解析

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