闭包|集创考核第九篇笔记

110 阅读1分钟

闭包

  • 变量作用域

    • 变量作用域的不同分为两种:全局变量和局部变量
    • 函数内部可以使用全局变量
    • 函数外部不可以使用局部变量
    • 当函数执行完毕,本作用域内的局部变量会销毁
  • 什么是闭包

    • 闭包(closure)指有权访问另一个函数作用域中变量函数

    • 使用变量所在的函数为闭包函数

    • 简单理解就是:一个作用域可以访问另外一个函数内部的局部变量

      //闭包:fun这个函数作用域   访问了另外一个函数fn  里面的局部变量num
      function fn() {
          var num = 10;
          function fun() {
              console.log(num);
          }
          fun();
      }
      fn();                    //输出10
      
    • 在fn外面的作用域可以访问fn内部的局部变量

      function fn() {
         var num = 10;
          function fun() {
              console.log(num);
          }
          return fun;
      }
      
      var f = fn();
      f();                 //外面f的作用域调用了fn内部的num局部变量,因为将fun返回给了f,fn为闭包
      
    • 闭包是典型的高阶函数

    • 闭包的主要作用:延申了变量的作用范围

  • 闭包案例

    • 循环注册点击事件(利用闭包立即执行函数传入i,这样立即执行函数里面的函数就都能使用i)

       <ul class="nav">
              <li>榴莲</li>
              <li>臭豆腐</li>
              <li>鲱鱼罐头</li>
              <li>大猪蹄子</li>
          </ul>
      
          <script>
              //闭包应用-点击li输出当前li的索引号
              //可以利用动态添加属性的方式
              var lis = document.querySelector('.nav').querySelectorAll('li');
              for(var i =0 ;i < lis.length;i++) {
                  lis[i].onclick = function() {
                      console.log(i);            //因为点击事件是异步任务,for是同步任务,所以当点击时for循环已经完成,此时点击输出为4
                  }
              }
              
              
              //利用闭包的方式得到li的索引号
              for(var i =0;i < lis.length;i++) {
                  //利用for创建了4个立即执行函数
                  (function(i) {
                      // console.log(i);
                      lis[i].onclick = function() {
                          console.log(i);                           //此时onclick的function函数使用了外部立即执行函数的i,产生了闭包,即立即执行函数为闭包
                      }
                  })(i);                   //后面的括号表示执行函数,在执行时传入实参i(当前循环的i),所以前面的function需要有i作为形参
              }
          </script>
      
    • 循环中的setTimeout()

      <ul class="nav">
              <li>榴莲</li>
              <li>臭豆腐</li>
              <li>鲱鱼罐头</li>
              <li>大猪蹄子</li>
          </ul>
      
          <script>
              //闭包应用:在3秒钟之后,打印所有li元素的内容
              var lis = document.querySelector('.nav').querySelectorAll('li');
              for(var i = 0;i < lis.length; i++) {
                  (function(i) {
                      setTimeout(function() {
                          console.log(lis[i].innerHTML);           //因为setTiomout的function也是异步任务,所以需要利用闭包传入当前的i,执行同步任务for循环将四个异步计时器推入执行栈,再同时调用异步回调定时器函数(延迟函数的回调)
                      },3000)
                  })(i);
              }
          </script>
      
    • 计算打车价格

          <script>
              //闭包应用-计算打车价格
              //打车起步价13(3公里内),之后每多加一公里增加5块钱。用户输入公里数就可以计算打车价格
              //如果有拥堵情况,总价格多收取10块钱拥堵费
              var car = (function() {
                  var start = 13;   //起步价    局部变量
                  var total = 0;    //总价      局部变量
                  return {         //以下两个函数都用到上面立即执行函数的局部变量,因此立即执行函数为闭包
                       //正常的总价
                      price:function(n) {
                          if(n <= 3) {
                              total = start;
                          } else {
                              total = start + (n - 3) * 5 
                          }
                          return total;
                      },     
                      //拥堵的费用
                      yd:function(flag) {
                          return falg ? total + 10 :total
                      }            
                  }
              })();
             console.log( car.price(5));         //23
             console.log(car.yd(true));            //33
      
             console.log( car.price(1));         //13
             console.log(car.yd(false));       //13
          </script>
      
  • 闭包总结

    • 闭包是什么?

      • 闭包是一个函数(一个作用域可以访问另外一个函数的局部变量)