闭包

作者: 斐硕人 | 来源:发表于2017-03-09 22:34 被阅读0次

    整理一下对闭包的理解

    var fn = null; //定义全局变量 fn
    function foo() {
      var a = 2;
      function innerFoo() { //定义内部函数 innerFoo
        console.log(a);
      }
      fn = innerFoo; //将 innerFoo 赋值给全局变量 fn
    }
    
    foo(); // undefined
    fn(); // 2
    

    为什么要用闭包呢?

    1. 我们想要在当前作用域之外,访问函数 foo 内部的变量 a。
    2. 当函数 foo 执行完毕后,生命周期结束,其函数的上下文失去引用,占用的内存空间很快就会被垃圾回收期释放。闭包会阻止这一过程。
    3. 尽可能少的全局变量。
    4. 在 JavaScript 中内部函数可以访问外部函数的上下文。
    console

    什么是闭包呢?

    当函数(内部函数)可以记住并访问所在的作用域(全局作用域除外)时,就产生了闭包,使函数在当前作用域外执行。

    在例文代码中闭包是什么呢?

    foo 是闭包(Chrome 浏览器认为),而不是之前一直认为的 innerFoo 。

    闭包的应用

    延迟函数柯里化模块
    以延迟函数为例:

    function fn() {
      console.log("hello world");
    }
    
    var timer = setTimeout(fn,1000);
    timer;
    
    console_2

    执行 timer 时,返回这个 setTimeout 的 ID,表明 setTimeout 函数本身已经执行完毕。一秒钟之后,fn (保存在 setTimeout 的变量对象中)才会执行。
    按理来说一秒后 setTimeout 执行结束后,fn 也就不存在了,但是事实上依旧输出了 hello world。
    这正是由于闭包。setTimeout 保留了 fn 的引用,使 fn 没有在其执行完毕后被垃圾收集器回收。由此 setTimeout 执行结束后一秒,我们仍能使用 fn 。

    带来的问题-内存泄露

    • 闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题。

    • 由于IEjs 对象和DOM 对象使用不同的垃圾收集方法,因此闭包在IE中会导致内存泄露问题,也就是无法销毁驻留在内存中的元素。

    • 解决思路:在函数之前,将不使用的局部变量全部删除。

    • 赋值 null,解除引用

    function closure(){
        var element = document.getElementById('someElement');//element用完之后一直驻留在内存中
        element.onclick = function () {
            alert('element.id');//这里用element导致内存泄露
        };
    }
    closure();
    //解决
    function closure(){
        var element = document.getElementById('someElement');
        var id = element.id; //将element.id保存在一个变量中,然后在内部函数中引用,消除对该变量的循环引用。
        element.onclick = function () {
            alert('id');
        };
        element = null;  //将element解除引用来避免内存泄露
    }
    
    • 在外面包一层匿名自执行函数
     (function () {
      ...//闭包
            })();
    //好处:不会污染全局变量,在匿名函数执行完了里面的的变量就释放掉了
    

    相关文章

      网友评论

          本文标题:闭包

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