JS作用域

86 阅读2分钟
  • JS没有块级作用域 ES6新增块级作用域概念

全局作用域

-   在页面打开时被创建 在页面关闭是被销毁

-   在script标签内写的都为全局作用域 在页面内的任意位置都能访问

    ```
      <script>
       var a = 1
      </script>  
    ```

-   全局作用域有一个全局 window对象,代表一个浏览器窗口 由浏览器创建,可以直接调用

-   全局作用域声明的变量会在window对象中保存

函数作用域

-   函数在调用时会创建一个函数作用域 在调用完成后会被销毁
-   每调用一次函数都会创建一个新的函数作用域,之间是相互独立的
-   函数作用域中可以访问函数作用域中的变量 ,在函数中声明的变量只能在函数中访问
-   在函数作用域中访问变量 函数会先找此函数内部声明变量 然后依次向上级查找

作用域理解

  • 执行期的上下文

    1. 当函数代码执行的前期(预编译)会创建一个执行期的上下文的内部对象AO(作用域)

    2. 这个AO对象是在函数预编译期间创建的 在函数调用之前创建

    3. 在全局代码执行的前期会创建一个预编译的上下文对象GO

      // 函数声明 
      function functionName(arg1, arg2, ...){
          <!-- function body -->
      }
          
       // 函数表达式的典型格式:
      variable = (arg1, arg2, ...)=>{
                  <!-- function body -->
      }
       
      
        function add(e,f){
          console.log(e,f,a)  //e() f() undefined
           var f = 3
           var e = 3
          function f(){
          }
          function e(){
          }
          //函数的表达式
          var a = ()=>{}
          console.log(e,f)
      ​
        }
       
        add(1,2)
        // 1 创建AO对象
        // 2 找形参和变量声明 将变量和形参的名 当做AO对象的属性名 值为undefined
        // 3 实参形参统一  
        // 4 在函数体中找函数 值为undefined
         AO = {
           e:undefined 1 fn,
           f:undefined 2 fn,
           a:undefined
      ​
         }
      

      作用域链

      • 会被保存到一个隐式的属性中去[{scope}] 这个属性用户访问不到 但是的确存在 让js引擎来访问 里面存储的就是作用域链 AO GO 的集合
      let globalfunction a() {
        function b() {
          var aa = 123
          bb = 0
        }
        var bb = 123
        b()
      }
      a()  
      ​
      

        graph LR;  
          a['a定义 scope']-->SCOPE;     
          SCOPE-->GO['全局预编译产生 '];
    
         graph LR;  
      a['a函数内部 ']-->作用域链顶端是自己的AO;     
      作用域链顶端是自己的AO-->GO['第二层是GO '];
    
        graph LR;  
        b['b函数内部 ']-->作用域链顶端是自己的AO;     
        作用域链顶端是自己的AO-->AO['第二层是a函数的AO '];
        AO['第二层是a函数的AO ']-->第三层是GO;