我对于闭包的简单理解

什么是闭包

简单来说:闭包就是能够用于获取其他函数内部变量的函数

什么是作用域

要理解闭包就要先理解作用域。

JavaScript 的作用域就两种:全局作用域局部作用域。其实还有第三种 eval(),但是不建议使用,所以在这里不讨论。

全局作用域: 在函数外部定义的变量就是 全局变量
局部作用域: 在函数内部定义的变量就是 局部变量

在函数内部可以读取函数外部或者全局的变量,但是在函数外部无法读取函数内部的局部变量。
这句话怎么理解?可以看个例子。

例子 1:

    var sName = 'Rogers';   // 这是全局变量
    function fn1(){
        console.log(sName);     // 函数内部可以读取全局变量
    }
    fn1();       // 终端中输出 ‘Rogers'

说明在 fn1() 函数内部可以读取全局变量

来看一个例子。

例子 2:

    function fn2(){
        var sName = 'Lewis';        // 函数内部的局部变量
    }
    console.log(sName);     // 错误:Uncaught ReferenceError: sName is not defined

说明在函数的外部无法读取函数内部的变量

再来看一个例子

例子 3:

    function fn1(){
        var sName = 'Jimmy';
        
        function fn2(){
            console.log(sName);     // Jimmy
        }
        fn2();

    }
    fn1();

那么,如果我们就是想在函数的外部获取函数内部的局部变量呢?怎么办?用正常的方法是办不到的,可以用变通的方法办到。那就是在函数的内部再定义一个函数。就像上面的例子3一样。函数 fn1 是外部函数,函数 fn2 是内部函数。就像上面写的一样,内部函数可以获取外部函数的变量,所以 fn2 这个内部函数就可以获取外部函数 fn1 的变量。然后再把它作为返回值返回就可以了。于是我们就可以再外部使用内部函数的变量了。

来看个和例子3差不多的例子:

例子 4:

    function fn1(){
        var sName = 'Johnson';

        function fn2(){
            return sName;
        }
        return fn2;
    }

在外部函数 fn1 的内部有变量 sName 和内部函数 fn2 。对于 fn2 来说, sName 就是它的外部变量,所以它可以获取 sName,然后再返回它。

    var f = fn1();
    console.log(f());   // 'Johnson'

所以我们就可以在外部获取函数内部的变量了。

什么用?

闭包有什么用?这是我们要搞清楚的。闭包主要有两个用处:
1,我们上面说了,就是获取函数内部的变量。
2,另一个作用,就是让变量始终保存在内存

第二点该怎么理解?我们知道变量如果不再使用了,那么垃圾回收器就会收回它,用于释放内存。比如说一个函数执行完毕之后,函数内部的变量就不再需要了,那垃圾回收器(GC)就会收回变量,释放内存。但是由于有闭包的存在,内部函数还在使用外部函数的变量,这就导致了外部函数的变量无法被回收。那么外部函数也会继续存在在内存中。所以它就会始终保持在内存中。

注意点: 由于闭包的存在,要注意内存泄漏问题。

写作日期:2018.11.10