10分钟了解闭包 closure

250 阅读2分钟

MDN官方定义

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

可能由于是翻译问题,这段定义读的实在绕,不懂可接着看下面。

闭包最简代码

先来看一段闭包的最简代码

    let codeHua=22222;
    function closure() {
        let codeHua = 1; // codeHua是父函数closure 创建的局部变量
        function displaycodeHua() { // displaycodeHua() 是子函数,一个闭包
            console.log(codeHua); // 使用了父函数中声明的变量
        }
        displaycodeHua();//1
        }
    closure();

初步理解

闭包是函数里面套函数,然后子函数能拿到父函数的变量。

闭包代码升级

接下来我们对代码进行一个升级,父函数中不执行子函数,而是返回子函数,并在每次log后++

    let codeHua=22222;
    function closure() {
        let codeHua = 1; // codeHua是父函数closure 创建的局部变量
        function displaycodeHua() { // displaycodeHua() 是子函数,一个闭包
             console.log(codeHua); // 使用了父函数中声明的变量
             codeHua++;//增加1
            }
         return displaycodeHua;//返回子函数
        }
    console.log(closure());// function displaycodeHua() {console.log(codeHua);}
    let myclosure=closure();
    let anothermyclosure=closure();
    myclosure();//1
    myclosure();//2
    myclosure();//3
    anothermyclosure();//1

在一些编程语言中,一个函数中的局部变量仅存在于此函数的执行期间。一旦closure() 执行完毕,name变量将不能再被访问,程序无法运行。

然而在JavaScript却可以正常运行,正是因为形成了闭包。

定义理解

我们回到广官方定义的一段话:

 闭包是由函数以及声明该函数的词法环境组合而成的,而该环境包含了这个闭包创建时作用域内的任何局部变量。

 

在上述代码中,myclosure是执行closure时创建的displaycodeHua函数的引用,displaycodeHua函数维持了一个对它的词法环境(变量codeHua在于其中)的引用。因此,当myclosure被调用时,变量codeHua仍然可用,其值就被传递。

myclosure与anothermyclosure都是闭包,但是保存了不同的词法环境。

通俗点说就是闭包可以保留变量的值,不造成变量污染。

闭包的缺点

处理速度慢,内存消耗大,非特定任务不推荐使用。