zoukankan      html  css  js  c++  java
  • 闭包

    1.什么是闭包?

    (1)函数嵌套函数

    (2)内部函数可以引用外部函数的参数和变量

    (3)参数和变量不会被垃圾回收机制所收回。因为内部函数bbb还在被引用着,所以需要长期驻扎在内存中。

    function aaa(a){
      var b=5; 
      function bbb(){
         alert(a);
         alert(b);  
    }   
    }
    
    aaa();//a和b都是可以访问的到的

    这就是闭包

    function aaa(){
        var a = 5;
        function bbb(){
            alert(a);
        }
        return bbb;
    }
    
    var c = aaa();//因为aaa()函数返回的是bbb
    
    c();//此时c()就相当于bbb()

    返回的结果就是:5

    2.什么是垃圾回收机制?

    //JS中的垃圾回收机制
    
    function aaa(){
        
        var a = 1;
        
    }
    
    aaa();

    变量a会被JS中垃圾回收机制收回,就不存在了。

     3.闭包有什么好处?应用在哪里?

    好处:(1)希望一个变量长期驻扎在内存当中
       (2)避免全局变量的污染
            (3)私有成员的存在

    栗子1:全局变量的污染:a是全局变量

    var a = 1;
    function aaa(){
        a++;
        alert(a);
    }
    
    aaa();  //2
    aaa();  //3
    
    alert(a);//3

    栗子2此时a是局部变量,每执行一次,就进入垃圾回收机制,所以每次执行aaa()函数,结果都是2

    function aaa(){
        var a = 1;
        a++;
        alert(a);
    }
    aaa();  //2
    aaa();  //2

    栗子3:利用闭包,变量a是局部变量

    function aaa(){
        var a=1;
        return function(){
            a++;
            alert(a);
        }
    }
    
    var b=aaa();
    b();  //2
    b();  //3
    alert(a); //a is not defined,因为a不是全局变量,访问不到a

    用法:
    1.模块化代码
    2.在循环中直接找到对应元素的索引

    栗子4:模块化代码

    function aaa(){
        alert(1);
    }
    aaa();
    
    //这两个函数结果是一样的,不同的是下面的(function(){
        alert(1);
    })是一个函数表达式
    
    (function(){
        alert(1);
    })();
    var aaa=(function(){
        var a=1;
        return function(){
            a++;
            alert(a);
        }
    })();
    aaa();  //2
    aaa();  //3

    栗子5有私有成员的存在,变量a,函数bbb(),函数ccc()

    var aaa=(function(){
        var a=1;
    
        function bbb(){
            a++;
            alert(a);
        }
    
        function ccc(){
            a++;
            alert(a);
        }
    
        return {
            b:bbb,
            c:ccc
        }
    })();
    
    aaa.b();  //2
    aaa.c();  //3,为什么是3呢?因为a相对于bbb函数和ccc函数,是全局变量,所以函数bbb执行后,a=2了,再执行ccc函数就是3了

     栗子6:在循环中直接找到对应元素的索引

    方法一:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>无标题文档</title>
    <script>
    window.onload = function(){
        var aLi = document.getElementsByTagName('li');
        for(var i=0;i<aLi.length;i++){
            (function(i){
    
                aLi[i].onclick=function(){
                    alert(i);
                }
            })(i);//将i参数传进去,存在内存中。
        }
    
    };
    
    </script>
    </head>
    
    <body>
    <ul>
        <li>11111111111</li>
        <li>11111111111</li>
        <li>11111111111</li>
    </ul>
    </body>
    </html>

    这样得到的结果是,点击哪一个按钮,就弹出那个位置的索引

    方法二:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>索引</title>
        <script>
            window.onload=function(){
                var lis=document.getElementById('test').getElementsByTagName('li');
                for(var i=0;i<lis.length;i++)
                {
                    lis[i].index=i;
                    lis[i].onclick=function(){
                        alert(this.index);
                    };
                }
            }
        </script>
    </head>
    <body>
        <ul id="test">
            <li>这是第一条</li>
            <li>这是第二条</li>
            <li>这是第三条</li>
        </ul>
    </body>
    </html>

    4.闭包需要注意的地方?

    在IE下有可能闭包引发的内存泄露问题及解决方案

    内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

    内存泄露 memory leak,是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重无论多少内存,迟早会被占光。

    memory leak会最终会导致out of memory!

    内存溢出就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出。 

        内存泄漏是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete)结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出!比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出. 

    栗子7:这样就会引发内存泄漏,除非关掉浏览器。

    window.onload = function(){
    	var oDiv = document.getElementById('div1');
    	
    	oDiv.onclick = function(){
    		alert(oDiv.id);
    	};
    

    为什么这样会引发内存泄漏?

    因为dom已经获取到了div1的节点,下面的oDiv的属性onclick里面的函数又存在访问oDiv的属性id,这样就形成了内存泄漏。

    解决方案:

     第一种:

    window.onload = function(){
        var oDiv = document.getElementById('div1');
        
        oDiv.onclick = function(){
            alert(oDiv.id);
        };
        
        window.onunload = function(){
            oDiv.onclick = null;
        };
        
    };

    onunload 事件在用户退出页面时发生。页面退出时,将onclick属性释放。

    第二种:将需要用的id先获取到,最后将oDiv释放。

    window.onload = function(){
        var oDiv = document.getElementById('div1');
        
        var id = oDiv.id;
        
        oDiv.onclick = function(){
            alert(id);
        };
        
        oDiv = null;
        
    };
  • 相关阅读:
    C# QRCode、DataMatrix和其他条形码的生成和解码软件
    windows系统 安装MongoDB 32位
    ubuntu下创建c语言程序之hello world
    ueditor 添加微软雅黑字体 异常“从客户端中检测到有潜在危险的 request.form值”,解决
    asp.net ueditor 图片上传路径问题解决
    C# winform线程的使用 制作提醒休息小程序(长时间计算机工作者必备)
    jquery.qrcode和jqprint的联合使用,实现html生成二维码并打印(中文也ok)
    javascript陷阱之in语句
    谈谈Python的深拷贝和浅拷贝
    Flask开启多线程、多进程
  • 原文地址:https://www.cnblogs.com/GumpYan/p/5695460.html
Copyright © 2011-2022 走看看