闭包恍然大悟

原文地址:https://www.cnblogs.com/xxcanghai/p/4991870.html

闭包最重要的一个作用就是把某些变量隐藏起来,让外面的程序不能直接访问。只要不是为了这个目的的闭包都可以取消。当然有时候为了组织代码,也会用闭包来进行一下封装,给代码分段,毕竟如果不用模块管理库的话,就会把很多模块都写在一个文件里,看起来确实痛苦。

闭包呢,说起来也了解了,但是现在在工作中也不知道用到了没,有没有造成内存泄漏。所以,我还是没认识到闭包,因为我不知道什么时候用,为什么用,会有什么好处,造成什么影响?

对于闭包的简单描述:

  • 在函数里嵌套函数

  • 父函数 return 子函数 function par (){

    var a = 0 ;

    retrun function child(){

    a++;

    console.log(a);

    retrun a ;

    }

    }

  • 通过父函数调用了子函数。 var child = par();

    child();

重点来了:

闭包里函数可以访问外部函数的作用域,即子函数可以访问父函数里的变量,当这个子函数被调用,而且这个子函数又引用了父函数的变量,所以父函数的作用域不会被回收,也就是说父函数里的a一直存在。有的时候,我要在一个点击事件里,通过点击的次数是偶数还是奇数来做不同的操作。肯定得有一个变量保存点击的次数。我一般会用一个全局变量来保存点击次数。之前也想到过,用闭包里父函数作用域里的变量保存点击次数,用子函数来改变量的次数。于是**

$btn.click(function(){
    var count = par()();
    console.log(count);
    if(count%2==0){
        alert("我是偶数");
    }else{
        alert("我是奇数");

    }
});
但是每次输出的count都是1;也就是每次都是从0开始加。不是说闭包里不会回收变量的吗?

其实一想,每次点击的时候 par()();不就是每次都调用了父函数,在调用的子函数,这样当然每次都会执行复函数里的 a = 0;从而在执行子函数是是从0开始加起来的。要是不调用父函数,我也得不到子涵呀?于是干脆还是用全局变量得了。

今天才理解到,先把子函数用变量保存起来,再调用。难怪那些讲解闭包的文章里都是把子函数先用变量接收!

var changeStatus = par();
$btn.click(function(){
    var count = changeStatus();
    console.log(count);
    if(count%2==0){
        alert("我是偶数");
    }else{
        alert("我是奇数");

    }
});

现在闭包里的变量没被GC——垃圾回收的状态实现了 ,可是又让我理解的头晕的是,用变量接收的子函数,每次在调用的时候怎么不也是调用了父函数?变量到底是个什么东西,保存赋值后发生了什么这么神奇的事。用变量接收的 var changeStatus = par(); 和 直接的 par () ; 不是同一个东西吗?要说是构造函数每次 new 出来的实例,那的确是不一样,每一个都是新的对象。这样用变量保存的子函数是和构造函数的实例是一回事吗?

我又专门打印了一下这个用变量接收的子函数,确实只有子函数的部分。我倒也是理解,如果直接 child()调用子函数是报错的。因为这样直接调用是在wido作用域下调用,也就是找不到这个子函数。那可以这样理解:通过父函数返回的这个子函数让变量 changeStatus 引用到了子涵数,也就是找到了这个子函数,所以每次调用变量,都是可以调用这个子函数,根据闭包的原理,可以访问到父函数的作用域,使父函数不被回收。

到现在对闭包的了解深了一些,不过关于用变量保存的子函数,与有直接调用父函数 par()返回的子函数之间有什么不同,还是模糊。并且有意思的是。用变量子函数changeStatus() 改变父作用域里的变量后,再直接通过父函数返回子函数调用子函数 par()(),居然对changeStatus() 的结果没影响,再调用changeStatus(),还是接着它上一次的结果。仿佛每次par()()都重新创建了一个作用域。父作用域不都是来自 pa r函数吗 ?

Last updated