闭包

144 阅读2分钟

闭包

    闭包指能被访问的自由变量的函数
    什么是自由变量?
    自由变量指的是:在函数中使用:既不是函数的参数,也不是函数的局部变量的变量
    
    基础版闭包
    函数内部 return 函数就是闭包哦
    闭包的缺点,导致内存泄漏
    闭包两个优点:1: 防止变量污染  2 函数内部变量可以被函数外部访问
    
    
    
    function foo(){
        var count = 0;
        return function (){
            console.log(++count);
        }
    }

    var res= foo();
     1: res 是不是函数?  是
     2:res 执行是 是否引用了 foo 中的count 变量。引用自由变量  是
     ----> res 是不是闭包      是
    res(); // 1
    res(); // 2
    res(); // 3

    res1 是新的闭包
    var res1 = foo();
    res1(); // 1
    res1(); // 2

    res 与 res1 是两个彼此独立的闭包互不干扰

     看几个独立的闭包;
     关键看 外层函数执行几次  
    foo()()
    foo()()

闭包的缺点

function foo() {
        var count = 0;
        return function () {
            console.log(++count);
        }
    }
    var res = foo();// res 引用了函数 范文了自由变量所以res是闭包
    res()
    res()
    var a = foo();
    var b = foo();
    var c = foo();
    a b res 四个独立的闭包
    所以引用了 4个独立的count 
    闭包过多是,count 过多,一直不释放 内存泄漏

   为什么 闭包导致内存泄漏?
   因为:return 函数被【外部变量所引用】,导致存在多个自由变量,又因为自由变量在浏览器关闭时候释放,所以内存泄漏

   简单理解:因为foo return函数被外部变量引用,导致foo 中变量不释放,所以内存泄流

   决方案 1:标记清除法实现零引用
    res = null;
    a   = null;
    b = null;
    c = null;
    

闭包优点

    实现变量私有化,防止全局变量污染或者变量之间相互污染

    什么是变量污染 
    var a = 123;
    var a= 456;
    我现在想要的的是123
    console.log(a); // 456 ----> a 被污染
    

    go{a:undefined} 

    变量污染,污染全局变量
    var a = 0 ;// go{a:0}
    function foo(){
        console.log(++a);  
    }
    foo(); // go:{a:1}
    foo(); // go:{a:2}
    foo(); // go:{a:3}

    console.log(a); // 0 

    
    
    
    
    
    
    
    需求:全局下 a 必须 0  , 同时也希望输出1,2,3
     var a = 0;
    function foo(){
        var a = 0;
        return function(){
            console.log(++a);
        }
    }
    var bar = foo();
    bar();
    bar();
    bar();
    console.log(a);//0
    

立即执行函数

立即执行函数特点:没有函数声明提升。自动执行,没有被其他变量引用
匿名函数都没有函数提升的过程
  使用立即执行函数 解决闭包内存泄漏问题
    立即执行函数,在浏览器加载时候执行;
    执行是创建变量,并赋值, 虽然 res a b c 是闭包
    执行完毕是后;变量会销毁 (res a b c 销毁)
    所以 解决了内存泄漏

    (function (global){
       

        function foo() {
            var count = 0 ;
            return function(){
                console.log(++count);
            }
        }

        var res = foo();
        res();
        res();
        var a = foo();
        a();
        a()
        var b = foo();
        b()
        var c =  foo();
    })(window)