什么是闭包?

函数与对其状态即词法环境(lexical environment)的引用共同构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在JavaScript,函数在每次创建时生成闭包。--出自MDN
词法环境:这个环境包含了这个闭包创建时所能访问的所有局部变量

当函数可以记住并访问所在词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。 - - 出自《你不知道的JavaScript(上卷)》

函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为"闭包" - - 出自《JavaScript权威指南》

闭包的作用

  • 延长内部变量的生命周期
  • 可以读取函数内部的变量

例子

function fu() {
   var a = 10
   function fun() {
      console.log(a); //闭包
     }
      fun()
 }
 fu()
function fu() {
    var a = 10;

    function fun() {
        console.log(a)
    }
    return fun;
}
fu()();

问题: 循环绑定点击时间,输出为全局变量

    <ul>
      <li><button>点击1</button></li>
      <li><button>点击2</button></li>
      <li><button>点击3</button></li>
      <li><button>点击4</button></li>
    </ul>
    <script>
      const list = document.querySelectorAll("li button");
      for (var index = 0; index < list.length; index++) {
        list[index].addEventListener("click", function () {
          console.log(index);
        });
      }
    </script>

输出都是4
解决方案

  • 使用闭包
    <ul>
      <li><button>点击1</button></li>
      <li><button>点击2</button></li>
      <li><button>点击3</button></li>
      <li><button>点击4</button></li>
    </ul>
    <script>
      const list = document.querySelectorAll("li button");
      for (var index = 0; index < list.length; index++) {
        (function (index) {
          // 形成闭包作用域
          //index局部变量永久储存
          list[index].addEventListener("click", function () {
            console.log(index);
          });
        })(index);
      }
    </script>

使用闭包永久保存变量

  • 使用let关键字
      function test() {
        /**
          局部变量 arr i
          局部作用域
          嵌套函数的闭包作用域
        */
        var arr = [];
        for (var i = 0; i < 10; i++) {
          (function (j) {
            /**
             * 局部变量 j
             * arr i 在此作用域引用,永久储存
             * 嵌套函数的闭包作用域
             */
            console.log(i); //上一级的局部变量在此作用域引用,都能永久储存
            console.log(j);//当前作用域的变量下一个嵌套函数引用,将永久储存
            arr[j] = function () {
              /*
                没有局部变量
                j在此作用域引用,永久储存
              */
              document.write(j + " "); // 输为0,1,2,3,4,5,6,7,8,9
            };
          })(i); //用立即执行函数(立即执行函数也可以生成自己的作用域) i作为参数传给j j不会随着i改变而改变
        }
        return arr;
      }
      var myArr = test();
      for (var j = 0; j < 10; j++) {
        myArr[j]();
      }

1616264001(1).jpg
1616263952(1).jpg

总结: 闭包就是在嵌套函数中引用上一级函数的局部变量,从而形成闭包作用域,引用的变量能够永久储存

Last modification:March 21st, 2021 at 02:19 am
如果觉得我的文章对你有用,请随意赞赏