美文网首页饥人谷技术博客
简单理解JS中的闭包

简单理解JS中的闭包

作者: 落木兮兮 | 来源:发表于2015-12-30 16:41 被阅读359次

    定义一个函数
    <pre>
    function fn(a,b,...rest){
    var arr;
    ...
    function fn2(){
    引用外部函数fn的参数a,b...rest和局部变量arr

          };
    

    return fn2;

    }

    fn();
    </pre>

    当调用fn ()这个函数时,返回的是fn2()这个函数,fn()的相关参数和变量都保存在返回的函数fn2()中,这种结构就称为闭包。闭包就是函数fn2(),即能够读取其他函数内部变量的函数。

    a,b...rest,arr这些局部变量在fn()这个函数外是无法被读取的,但是有时候又想要读取这些变量,怎么办呢?

    在fn的内部再定义一个函数fn2(),fn2()是可以访问fn内部所有的局部变量的,在内部引用局部变量arr,将fn2()作为返回值,即可在外面调用fn的局部变量。

    <pre>
    function fn() {
    var n = 999;
    function fn2() {
    console.log(n);
    }
    return f2;
    }
    var result = fn();
    result(); //999
    </pre>

    调用fn()时,返回的并不是n的值,而是函数fn2(),因此我门要在外面将fn赋给一个函数result,利用调用result();返回的值才是n的值。返回的函数并没有立刻执行,而是直到调用了result()才执行。

    另一个例子

    <pre>
    function lazy_sum(arr) {
    var sum = function () {
    return arr.reduce(function (x, y) {
    return x + y;
    });
    }
    return sum;
    }
    var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
    f(); // 15
    </pre>

    同样的,当我们调用lazy_sum()时,返回的并不是求和结果,而是求和函数。调用函数f
    时,才真正计算求和的结果。

    当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数:
    <pre>var f1 = lazy_sum([1, 2, 3, 4, 5]);
    var f2 = lazy_sum([1, 2, 3, 4, 5]);
    f1 === f2; // false
    </pre>

    f1()和f2()的调用结果互不影响。

    于在JavaScript语言中,只有函数内部的子函数才能读取内部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。闭包最大的特点,就是它可以“记住”诞生的环境,比如fn2记住了它诞生的环境fn,所以从fn2可以得到fn的内部变量。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

    闭包的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量始终保持在内存中,即闭包可以使得它诞生环境一直存在。

    内存泄露

    因为result();一直存在在内存中,而result()的存在依赖于fn,因此也始终在内存中,不会在调用结束后,被垃圾回收机制回收,内存一直得不到释放,JS释放内存时就会漏掉这一部分,渐渐越积越多,造成内存泄露。

    返回函数不要引用任何循环变量,或者后续会发生变化的变量。

    相关文章

      网友评论

        本文标题:简单理解JS中的闭包

        本文链接:https://www.haomeiwen.com/subject/vbpihttx.html