前言

说到闭包真的是让我头大的货色,始终以来都只是一个概念,平时也简直不必,所以始终都没太搞懂。都是最近在看防抖,节流函数的写法,举荐应用闭包来写,所以才从新来了解闭包,防抖和节流之后也会独自写一篇文章来论述吧。

什么是闭包

MDN中对闭包的定义如下:

函数和对其四周状态(lexical environment,词法环境)的援用捆绑在一起形成闭包(closure)

上述句子换句话说就是:闭包是由函数及其援用的变量形成的。那么就有一个问题了,那岂不是所有函数只有外部援用内部的变量都能形成一个闭包,例如:

    let a = 1;    function printA(){      console.log(a);    }

依照定义的确上述例子也形成闭包,但怎么跟咱们平时见到的闭包不一样呢?

《JavaScript权威指南中》的确也写道:

从技术角度讲,所有的JavaScript都是闭包。

但从理论利用思考,这样的闭包就没有存在的意义,所以MDN补充道:

也就是说,闭包能够让你从外部函数拜访内部函数作用域。

<p style="color: red">所以援用的变量应该为函数作用域内的变量,换句话说,闭包应存在于函数作用域外部,例如:</p>

    //a与printA形成一个闭包    function func(){      let a = 1;      function printA(){        console.log(a);      }      printA();    }    func();

看到这个例子有人可能会想,怎么我看到的闭包都会return一个函数呀?实际上是一样的,return进来只是为了内部调用而已,实质上一样的嘛。

对于为什么可能在外部函数中援用内部函数的变量,对作用域稍有理解的人就会晓得:函数中援用变量时,会先从本身函数中读取,如果外部没有就逐层往上读取,直至读取到。这里特地提一点,函数依赖于变量作用域,这个作用域是在函数定义是决定的,而不是函数调用时决定的。(起源《JavaScript权威指南》) 所以寻找变量时应该从定义时的函数中往上寻找,而非调用时,举个例子:

    function func(){      let a = 1;      console.log(a);    }    let a = 2;    func();  //1

闭包的简略利用

后面说了那么多,那么闭包到底有什么用?闭包的常见用法就是提供间接拜访一个变量的办法,有时候咱们须要在某些中央用到一个变量,然而又不能定义为全局变量,存在着篡改的危险,那么咱们就能够用定义位公有变量,而后通过闭包裸露进来,例如通过闭包写一个计数器,代码如下:

    function count(){        let num = 0;            return {                add: function () {                    num++;                    return num;                },                sub: function () {                    num--;                    return num;                },                reset: function () {                    num = 0;                    return num;                }            }        }        let counter = count();        counter.add();  //1        counter.add();  //2        counter.sub();  //1        counter.reset(); //0        counter.add();  //1