闭包

354 阅读2分钟

闭包一般就是函数套函数。里面的函数一般都当作返回值。

变量的作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。

变量的作用域无非就是两种:全局变量和局部变量。

函数内可以根据链式作用域先访问函数内的变量,找不到在逐级向外找。

如何产生闭包?

当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量时,就产生了闭包。

函数内部引用了外部函数的(变量/函数),并执行了外部函数。

function fn1(){
    var a = 2
    var b = '123'
    // 执行函数定义就会产生闭包(不用调用fn2函数)
    function fn2(){
        //fn2引用了fn1的变量a,此时就产生了闭包
        console.log(a)
    }
}

闭包 外部不能访问到内部的变量和方法,

闭包的作用

  • 闭包可以延长函数内的局部变量的存活时间,函数执行完后,局部变量仍可以存活在内存中。
  • 在函数外部可以访问函数内部的局部变量
  • 闭包外部 不能访问闭包内部的变量和方法,起到隔离的作用。

正常情况下,函数中存在变量,函数执行完局部变量会被垃圾回收机制销毁。

function fn1(){
    var a = 2
    function fn2(){
        a ++
        console.log(a)
    }
    function fn3(){
        a--
        console.log(a)  //因为使用了a 产生了闭包 
    }
    return fn3
}
// 变量f接收了 函数对象fn3,暂存了fn3
var f = fn1()
f()  // 1
f() // 0 

闭包的缺陷

  • 闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露。
  • 如果不是因为某些特殊任务而需要闭包,在没有必要的情况下,在其它函数中创建函数是不明智的,因为闭包对脚本性能具有负面影响,包括处理速度和内存消耗。

闭包可以缓存局部变量

正常情况下闭包中的局部变量用完既被销毁,但是可以通过闭包延长变量存活时间。

    function fn1(){
        var a = 1;
        function fn2(){
            return a;
        }
        return fn2
    }
    
    var b = fn1();
    b(); // 1 

通过闭包解决问题

for(var i = 0;i<10;i++){
    (function(j){
        alert(i); // 打印 0 , 1 , 2 .....
    })(i);
}


通过闭包模块化

    (function(){
        var a = 1;
        function add(){
            a ++;
        }
        var b = {}
        b.add = add
        window.a = b
    })()
    
    //调用 window.a.add();