理解闭包,先了解一下Javascript变量的作用域。有两种,全局变量和局部变量。

  例子1:

<script>
    var a = 0;
    function fun(){
        var b = 0;
        console(a+" "+b);
    }    
</script>

a是全局变量,b是局部变量。函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。

  如何从外部读取函数内部的局部变量?

  例子2:

function fun(num){
    var b = 0;
    b += num;
    return b;
}
var re_b = fun(1);
console.log(re_b);    //1
re_b = fun(2);
console.log(re_b);    //2

fun()将局部变量b作为返回结果;

  例子3:

function fun(){
    var b = 0;
    function fun2(num){
        b += num;
        return b;
    }
    return fun2
}
var re_b = fun();
console.log(re_b(1)); //1
console.log(re_b(2)); //3  

简单分析一下例子3代码:

定义普通函数fun;

在fun中定义变量b,普通函数fun2(参数),返回fun2;

在fun2中将参数num与b相加后赋予b,返回b;

执行fun,并把返回结果赋予re_b,此时re_b的类型为function;

执行re_b(1),结果输出1(0+1);

执行re_b(2),结果输出3(1+2);

上述方法即为闭包。

在了解闭包的作用之前,我们先了解一下 Javascript 中的 垃圾回收 机制,在 Javascript 中,如果一个对象不再被引用,那么这个对象就会被 GC 回收,否则这个对象一直会保存在内存中。

例子2中,执行完fun,变量b就会被释放回收;

例子3中,fun2定义在fun中,即fun2依赖于fun,全局变量re_b引用fun2,fun就间接被引用,即fun和fun2与re_b共存亡。只要re_b没被释放回收,变量b就一直在内存中。这也就是闭包的作用,fun执行完并返回后,闭包使得Javascript的垃圾回收机制GC不会收回fun所占用的资源。

一句话说,当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。

  闭包的应用场景:保护函数内的变量安全;在内存中维持一个变量;通过保护变量的安全实现JS私有属性和私有方法。

  闭包的一个简单应用:

for(var i=0;i<5;i++){
    setTimeout(function(){
        console.log(i)
    },1000*i)
}
    

结果为,每秒钟输出一个5,一共输出5次。

 

for(var i=0;i<5;i++){
    (function fun(i) {
        setTimeout(function(){
       console.log(i)
        },1000*i)
    })(i)
}

结果为,每秒钟输出一个数,0,1,2,3,4。

第一个例子中每次循环中的setTimeout回调函数记住的i的值是for循环作用域中的值,此时都是5,而第二个例子记住的i的数为setTimeout的父级作用域自执行函数中的i的值,依次为0,1,2,3,4。

   注意点:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,滥用闭包,会造成网页的性能问题,在IE中可能导致内存泄露

 

posted on 2019-06-26 15:32  清谨  阅读(238)  评论(1编辑  收藏  举报