欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

简单理解Javascript闭包

程序员文章站 2022-04-29 20:37:07
理解闭包,先了解一下Javascript变量的作用域。有两种,全局变量和局部变量。 例子1: a是全局变量,b是局部变量。函数内部可以直接读取全局变量,但是在函数外部无法读取函数内部的局部变量。 如何从外部读取函数内部的局部变量? 例子2: fun()将局部变量b作为返回结果; 例子3: 简单分析一 ......

  理解闭包,先了解一下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中可能导致内存泄露