js基础—var全局作用域 ,局部作用域

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    //函数的声明提升
    /* 
      js引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。
      而函数表达式必须等到代码执行到那一行,才会在执行上下文中生成函数定义
    */
   //eg1:
    console.log(a);
    var a = 100;
    fn('小胖');//声明提升
    function fn(name){
    
    
      //var name="小胖";
      age=20;
      console.log(name,age);
      //var age;
    }
    //网页加载js文件的时候是从头开始的,当执行console打印语句时,
    //找不到,所以先赋值给undefined,然后全局找变量a包括函数体fn,将a提取出来
    //fn也提取出来,都提取出来之后,fn已经预加载了,所以fn()能够正常打印
    //函数的作用域和全局作用域

    //在函数中,使用var声明的变量,为局部变量,只能在函数内部访问。
    //不使用var声明的变量,为全局变量,在函数外也能使用
    //eg2:不适用var
    a=10;
    function one(){
    
    
      console.log(a);
      a=5;
      console.log(a);
    }
    one();
    console.log(a);
    //10
    //5
    //5
    //eg3:使用var
    var a=10;
    function two(){
    
    
      console.log(a);
      var a=5;
      console.log(a);
    }
    two();
    console.log(a);
    //undefined
    //5
    //10

    /* 
      作用域:一条数据在哪个范围中可以使用。
        作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突
    */
   /* 
      js的变量中,变量的作用域有两种,
      一种是全局作用域(全局变量),一种是局部作用域(局部变量),
      一个变量是全局变量还是局部变量,主要看变量声明的位置。
      局部作用域:
        **声明在函数内部,就是这个函数(function)的局部变量。
        **使用var在函数内部定义的变量
        **局部作用域只能在函数内部访问。
      全局作用域:在任何地方都能访问,
       **函数外定义的变量拥有全局作用域,
       **不使用var定义的变量拥有全局作用域,
       **所有window对象上的属性拥有全局作用域
       **没有声明在函数内部的函数拥有全局作用域   

   */
    var a = 100;
    function fn(){
    
    
      var a = 50; //局部作用域
      console.log(a);  //50
    }
    console.log(a);  //100

    /* 
      **js没有所谓的块级作用域,js的作用域是相对函数而言的,
      **可以称为函数作用域
    */
   /* 
      作用域链:根据内部函数访问外部函数变量的机制,
      用链式查找方式决定哪些数据能被内部函数访问到。
   */
  /* 
      js执行环境
        js为每一个执行环境关联了一个变量对象,
        环境中定义的所有变量和函数都保存在这个对象中。
        全局环境是最外围的执行环境,全局环境被认为是window对象,
        因此所有的全局变量和函数都是作为window对象的属性和方法创建的。
        的执行顺序是根据函数的调用来决定的,当一个函数被调用时,
        该函数的变量对象就被压入一个环境栈中,而在函数执行之后,
        栈将该函数的变量对象弹出,把控制权交给之前的执行环境变量对象。
  */
  //闭包:内部函数的作用域链仍然保持着对父函数活动对象的引用,称为闭包
  // 闭包的作用:
  //   1.读取自身函数外部的变量
  //   2.让这些外部变量始终保存在内存中
  function outer(){
    
    
      var result=new Array();
      for(var i=0;i<2;i++){
    
    //i是outer的局部变量
        result[i]=function(){
    
    
          return i;
        }
      }
      return result;//返回一个函数对象数组
      //初始化result.length个关于内部函数的作用域链
    }
    var fn=outer();
    console.log(fn[0]());
    console.log(fn[1]());
    //2
    //2
    //function内部的函数执行完毕以后,才会退出循环,进行下一步骤,输出最终结果

    //如何让result数组函数返回我们所期待的值
    /* 
        result的活动对象里有一个arguments,
        arguments对象是一个参数的集合,是用来保存对象的。
        把i当成arguments的参数传进去,这样一调用i就能锁定目标,
        找到arguments中的对象
    */
    function outer(){
    
    
      var result=new Array();
      for(var i=0;i<2;i++){
    
    
        //定义一个带参函数
        function arg(num){
    
    
          return num;
        }
        //把i当成参数传进去
        result[i]=arg(i);
      }
      return result;
    }
    //var fn = outer();
    console.log(outer()[0]);
    console.log(outer()[1]);
    /* 
      该方法调用内部函数时,父函数的环境变量还没被销毁,
      而且result返回的是一个整数型的数组,而不是一个函数数组。
      让arg(num)函数内部再定义一个内部函数。
      这样result返回的其实是innerarg()函数
    */
    function outer(){
    
    
     var result=new Array();
     for (var i=0;i<2;i++){
    
    
       //定义一个带参函数
       function arg(num){
    
    
         function innerarg(){
    
    
           return num;
         }
         return innerarg;
       }
       //把i当成参数传进去
       result[i]=arg(i);
     }
     return result;
   }
   var fn = outer();
   console.log(fn[0]());
   console.log(fn[1]());
   //上述代码中,当调用innerarg()时,
   //它会沿作用域链找到夫函数arg()活动对象里的arguments参数num=0;
   //函数arg在outer函数内预先被调用执行了,对于这种方法,js有一种简洁的写法
   function outer(){
    
    
     var result = new Array();
     for(var i=0;i<2;i++){
    
    
       //定义一个带参函数
       result[i]=function(num){
    
    
         function innerarg(){
    
    
           return num;
         }
         return innerarg;
       }(i)//预先执行函数写法,把i当成参数传进去
     }
     return result;
   }
   var fn = outer();
   console.log(outer()[0]())
   console.log(fn[0]());
   console.log(fn[1]());
  </script>
</body>
</html>

猜你喜欢

转载自blog.csdn.net/weixin_44158539/article/details/113831138