闭包

一、闭包定义

  函数嵌套函数,子函数访问父函数的变量,就产生了一个闭包环境
            function fn1(){
                var n=10;    //n是在函数内声明的,局部变量,它在函数外面是访问不到的
                function fn2(){        //fn2是在函数内声明的,局部函数,它在函数外面是访问不到的
                    n++;
                    console.log(n);            //11
                }
                fn2();
            }
            //fn2(); 这里是不能够访问到fn2的函数
            fn1();    //11
            fn1();    //11
            //console.log(n);        //报错
            那么如何让局部域的变量和函数,在全局被访问到?
二、生命周期与垃圾回收机制
                          生命周期
             *         变量或者函数在相应的作用域里存在的时间
             *         局部变量:不再使用了,就是生命周期的结束。局部变量是在函数内声明的,当函数执行完成以后,这个变量就不存在了
             *         全局变量:声明完成以后,在整个页面中都可以用。当页面关闭的时候,它的生命周期就结束了
 
             *         垃圾回收机制
             *         变量存在内存当中的,变量在使用完以后,没有在其它的地方再使用,就会被清除,用来释放内存。垃圾回收机制会按照固定                            的时间,周期性的执行
     1.     function fn1(){
                var b=12;
            }
            fn1();        
            
            //console.log(b);        //报错 变量b在函数fn1执行完成以后,发现在别的地方没有再使用,那它就会被垃圾回收机制所回收
            //就是局部作用是基于垃圾回收机制的
 
     2.     function fn2(){
                var n=10;
                function fn3(){
                    n++;
                    console.log(n);
                }
                fn3();
            }
            fn2();        //11
            fn2();        //11
            //fn2函数在执行完成以后,变量n在其它的地方没有被使用,所以n在fn2执行完成以后会被垃圾回收机制 所回收。再去设fn2的时候,此时内存当中已经没有n这个变量了,只不过是重新声明了一个n
 
三、闭包的作用
         让函数内的局部变量与局部函数,在外面(不一定是全局变量,只是相对于该局部的)可以访问到
       方法有两种
        1、定义一个全局变量,放入到局部域里面,然后将需要的局部变量和函数赋值给它,然后再全局就能调用。
            var innerFn=null;        //全局变量,用来存储内部函数
            function fn1(){
                var n=10;
                function fn2(){
                    n++;//n=n+1
                    console.log(n);
                }
                fn2();       //这里执行了函数之后得到的结果就是一个数
                
                innerFn=fn2;  
            }
            fn1();        //11
            
            innerFn();        //12        把fn2整个函数赋给了innerFn,而它本身就是一个全局变量,有了值以后在其它的地方就可以访问到它了
            innerFn();        //13          因为fn2变成了全局变量,因此它的变量没有被垃圾回收机制回收。因此不断累加
 
              2、将局部变量以及函数从局部域调出到全局域,那么在外面就能访问到了。      
            function fn1(){
                var n=10;
                function fn2(){
                    n++;
                    console.log(n);
                }
                
                return fn2;    //这里的意思是把fn2返回到了fn1的结果, 既是fn1()=function fn2(){};
            }
            console.log(fn1());        //fn1()=function fn2(){};
            var newFn=fn1();
            /* 相当于 var newFn=function fn2(){    相当于将fn2从局部的函数调出到了全局。并且把函数说明变成函数表达式
                     n++;
                     console.log(n);
            }*/
            newFn();        //11
            newFn();        //12
 
四、闭包的应用
        1.在循环中找到对应的值
  1. window.onload=function(){
  2. var lis=document.querySelectorAll('li');
  3. //var i=0;
  4. for(var i=0;i<lis.length;i++){
  5. //利用作用域访问的关系。不让i访问到for
  6. lis[i].onclick=(function(i){
  7. //这里给的形参就说明在这个局部域里面有i,所以找值得时候,找到这里就停了,不用找到上面一层for的i, for的i永远是length
  8. function fn2(){
  9. console.log(i);
  10. }
  11. return fn2;
  12. })(i); //相当于把fn2从里里面的域带了出现,但是i的值还是从里面开始查找起。
  13. }
  14. }
  15. <ul>
  16. <li>red</li>
  17. <li>green</li>
  18. <li>blue</li>
  19. <li>yellow</li>
  20. <li>pink</li>
  21. </ul>
 
posted @ 2017-02-24 14:34  CafeMing  阅读(168)  评论(0编辑  收藏  举报