zoukankan      html  css  js  c++  java
  • JS作用域与预解析

    作用域

    JavaScript(es6前)中的作用域有两种:

    • 全局作用域
    • 局部作用域(函数作用域)
    全局作用域

    作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。

    局部作用域

    作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。

    变量的作用域

    在JavaScript中,根据作用域的不同,变量可以分为两种:
    • 全局变量
    • 局部变量
    全局变量

    在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。

    • 全局变量在代码的任何位置都可以使用
    • 在全局作用域下 var 声明的变量 是全局变量
    • 特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)
    局部变量

    在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)

    • 局部变量只能在该函数内部使用
    • 在函数内部 var 声明的变量是局部变量
    • 函数的形参实际上就是局部变量
    全局变量和局部变量的区别
    • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
    • 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间

    作用域链

    只要是代码都在一个作用域中,写在函数内部的局部作用域,未写在任何函数内部即在全局作用域中。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;根据在[内部函数可以访问外部函数变量]的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链。

    作用域链:采取就近原则的方式来查找变量最终的值。

    案例一:

    function f1() {
        var num = 123;
        function f2() {
            console.log( num );
        }
        f2();
    }
    var num = 456;
    f1();          // 打印结果:123
    

    案例二:

    var a = 1;
    function fn1() {
        var a = 2;
        var b = '22';
        fn2();
        function fn2() {
            var a = 3;
            fn3();
            function fn3() {
                var a = 4;
                console.log(a); //a的值 ?
                console.log(b); //b的值 ?
            }
        }
    }
    fn1();        //a = 4 ,  b ='22' 
    

    ## 预解析

    预解析的相关概念

    JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。

    JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。

    • 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义。

    • 代码执行: 从上到下执行JS语句。

      预解析会把变量和函数的声明在代码执行之前执行完成。

      预解析也叫做变量、函数提升。

    变量预解析

    变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。

    案例一

     var num = 10
     fun()
     function fun(){
       console.log(num);    // 结果undefind
       var num = 20
      }
    
    // 相当于以下代码
    
    var num 
    function fun(){
         var num
         console.log(num);    // 因此打印的结果为 undefind
         num = 20
      }
    num = 10 
    fun()   
    

    案例二:

     var num = 10
     function fun(){
       console.log(num); // undefined  与案例一相同
       var num = 20;
       console.log(num);  //20
       }
     fun()
    
    //相当于以下代码
      var num
       function fun(){
          var num 
          console.log(num);  // 因为在函数内 有一个 未赋值的num 变量 根据就近原则 所以是undefined
          num = 20
           console.log(num); // 20
             }
       num = 10;
     fun()
    
    

    案例三:

     var a = 18;
     f1()
     function f1(){
         var b = 9;
         console.log(a);  // undefined
         console.log(b);  // 9
         var a ='123'
     }
    // 相当于以下代码
     var a 
     function f1(){
         var b
         var a
         b = 9
         console.log(a);
         console.log(b);
         a = '123'   
     }
    a = 18
    f1()
    

    案例四:

     f1();
     console.log(c);        // 9
     console.log(b);        // 9
     console.log(a);        // Uncaught ReferenceError: c is not defined
     function f1(){
         var a = b = c = 9;      // 这个地方 b和c都是相当于直接赋值,没有声名,所以是全局变量
         console.log(a);   // 9
         console.log(b);   // 9
         console.log(c);   // 9
     }
    
    // 相当于以下代码
    function f1(){
        var a                // 这里  a 是局部变量, b与c 都是全局变量。
            a= b = c = 9
            console.log(a);  // 9
            console.log(b);  // 9
            console.log(c);  // 9 
    }  
    f1()
    console.log(c);         // 9
    console.log(b);         // 9
    console.log(a);         // 9
    
    

    拓展:

    在函数内以 var a = b = c 这种形式进行变量声名时,a是函数内部变量,b和c都是全局变量。

    function fun(){
        var a=b=c=1
        console.log(a);  // 1
    }
    fun()
    console.log(b);     //  1
    console.log(c);     //  1
    
    
  • 相关阅读:
    CSS基础知识点
    HTML回顾
    stringbuffer与stringbuilder与String
    事务的概念与使用
    大数据处理对象CLOG BLOG
    小却常用的小知识点和技巧
    视图
    移位运算符
    规范化与范式
    聚集索引和非聚集索引
  • 原文地址:https://www.cnblogs.com/ymzi/p/12486462.html
Copyright © 2011-2022 走看看