美文网首页
理解闭包

理解闭包

作者: KATENGC | 来源:发表于2020-04-22 15:57 被阅读0次

    一、闭包的概念

    我们先来看一个简单的函数

    function foo(){
      var a=10;
      return a;
    }
    
    foo();// 2
    

    这里我声明了一个foo的函数,在该函数中有一个变量a,这个a属于局部变量,其作用域仅在函数中有效。
    这里调用结束后,这里的局部变量是可以被释放(与js的垃圾回收机制相关)了,正常来说foo函数调用完毕,为局部变量a分配的空间就会被回收了。

    我们稍微改动下上面的函数

    function foo(){
      var a=20;
      return function(){
        return a;
      }
    }
    
    var func=foo();
    func();// 20
    

    这里我们可以看到foo函数的返回是一个匿名函数,而这个匿名函数返回的是局部变量a。当执行foo()后,这个局部变量是不会被回收的,这就形成了一个闭包,我们在外部仍然可以调用变量a。

    我们来总结下。正常来说,函数内部的变量只能在该函数内使用,在函数外部是不能调用的,而闭包就是定义在函数内部的子函数,子函数中用到了父函数的参数或局部变量,局部在函数调用之后参数或者局部变量不会被回收,同时这个局部变量能在函数外部被调用到。(个人理解)

    二、闭包的作用

    那闭包的作用是什么呢?

    1.具有封闭性,可以保护变量不被回收

    function foo(){
      var num=1;
      function b(){
        num++;
        return num;
      }
      return b
    }
    
    var func=foo();
    func();// 2
    func();// 3
    

    上面我们可以看到,在foo函数中有定义了一个子函数b,而这个子函数中使用了上一级(父函数)中的局部变量num,所以就导致foo()调用后,这个局部变量num不会被回收。foo()返回一个函数,赋值给了func,第一次调用func()返回num++后的值(num=2)这个时候num就会保存起来了,不会被回收,第二次调用func()返回num++值(在num=2的基础上,在加1,num=3)

    2.避免全局变量污染

    var a=1;
    function foo(){
      a++;
      return a;
    }
    
    foo();// 2
    foo();// 3
    

    此时的a是全局变量,在程序中尽可能避免全局变量。那我们将变量a放到函数内试试

    function foo(){
     var a=1;
     a++;
     return a;
    }
    
    foo();// 2
    foo();// 2
    

    可以看到每一次foo()的执行结果都是2。这是因为变量a为foo函数的局部变量,每一次调用foo()完毕后,变量a都会被GC回收,下一次执行的时候,a又初始化为1,累加后输出2,所以永远输出的都是2

    那有没有办法能使局部变量a既避免被全局污染又能做到不会GC回收呢?
    答案是有的,我们可以利用闭包实现

    function foo(){
      var a=1;
      function b(){
        a++;
        return a;
      }
      return b;
    }
    
    var func=foo();
    func();// 2
    func();// 3
    

    三、使用闭包需要注意什么

    (1)因为闭包会导致局部变量会保存在内存中,这对内存消耗是很大的,所以不能滥用闭包,否则会影响网页的性能,在IE中可能会导致内存泄漏。如何解决?

    window.onload = function(){
        var oDiv = document.getElementById('div1');
        oDiv.onclick = function(){
            alert(oDiv.id);
        }
        //当页面跳转的时候把oDiv.onclick引用置为空就好了
        window.onunload = function(){
            oDiv.onclick = null;
        }
    }
    

    (2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值

    相关文章

      网友评论

          本文标题:理解闭包

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