zoukankan      html  css  js  c++  java
  • JS闭包的详解

    一、什么是闭包?

    特点:
    1 函数嵌套函数
    2 内部函数可以引用外部的参数和变量
    3 参数和变量不会被垃圾回收机制所回收

    举一个简单的闭包的例子,例子中符合闭包的三个特点

    function aaa(a){
        var b = 5;
        function bbb(){
            alert(a);
            alert(b);
        }
    }
    aaa();  
    

    关于js 中的垃圾回收机制,这里说明一下。请看下面代码,当aaa函数执行完毕之后,aaa中的变量a会被js的垃圾回收机制所回收

    function aaa(){
        var a = 1;
    }
    aaa(); // 改函数执行完毕时候,函数中的变量a会被js的垃圾回收机制所回收  
    

    再举一个闭包例子

    当aaa函数执行完毕之后,调用c函数仍然可以弹出1,说明了a这个变量没有被垃圾回收

    function aaa(){
        var a = 1;
        function bbb(){
            alert(a);
        }
        return bbb;
    }
    var c = aaa(); // 当aaa函数执行完毕之后,调用c函数仍然可以弹出1,说明了a这个变量没有被垃圾回收
    c();  
    

    二、闭包有什么好处?应用在哪?

    2.1 好处:

    1 可以使一个变量常驻内存
    2 避免全局变量的污染
    3 私有成员变量的存在

    举个例子,例子中,使用全局变量a实现每次调用aaa函数,变量a++,过多使用全局变量不容易维护(全局变量的污染)。

    var a = 1;
    function aaa(){
        a++;
        alert(a);
    }
    aaa(); //2
    aaa(); //3
    alert(a); // 这里的a是全局变量  
    

    下面,使用闭包实现这个例子:
    由于a是局部变量,防止了全局变量污染

    function aaa(){
        var a = 1;
        return function bbb(){
            a++;
            alert(a);
        }
    }
    var b = aaa();
    b(); //2
    b(); //3
    alert(a); // 由于a是局部变量,外面无法引用,程序报错  
    

    使用函数表达式的形式,改造上面例子
    关于函数表达式的知识点,可以查看JS函数声明与函数表达式的区别 http://www.cnblogs.com/linhp/p/6085567.html

    var aaa = (function (){
        var a = 1;
        return function bbb(){
            a++;
            alert(a);
        }
    })();// 这里已经执行了
    aaa(); //2
    aaa(); //3  
    

    私有成员变量的例子:
    将表达式中的函数bbb与ccc通过json的方式返回,外部只能调用返回的json中的函数bbb和ccc,而无法访问a这个成员变量。

    var aaa = (function (){
        var a = 1;
        function bbb(){
            a++;
            alert(a);
        }
        function ccc(){
            a++;
            alert(a);
        }
        return {b:bbb,c:ccc}
    })();
    aaa.b();
    aaa.c();  
    

    2.2 用法:

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

    模块化代码就不举例了,上面的代码都能体现
    下面举例(在循环中,直接找到对应元素的索引)
    先看下面例子:

    <script>
    window.onload = function (){
        var oLi = document.getElementsByTagName("li");
        for (var i = 0; i < oLi.length; i++) {
            oLi[i].onclick = function (){
                alert(i);
            }
        }
    }
    </script>
    <ul>
        <li>111111111111</li>
        <li>222222222222</li>
        <li>333333333333</li>
    </ul>  
    

    上面例子中,想通过给每一个li添加点击事件,点击每个li,弹出li的索引,而上面例子中,由于for循环已经结束,而onclick事件还没触发,此时i已经等于3了,所以你无论点击哪一个li都无法获取索引,弹出的值都是3

    下面,通过闭包的形式,改造,获取索引

    window.onload = function (){
        var oLi = document.getElementsByTagName("li");
        for (var i = 0; i < oLi.length; i++) {
            (function(i){
                oLi[i].onclick = function (){
                    alert(i);
                }
            })(i); //循环过程中,这里已经执行了。参数i永驻内存,所以当你点击li的时候,可以获取得到0,1,2
        }
    }   
    

    也可以改造成下面的样子

    window.onload = function (){
        var oLi = document.getElementsByTagName("li");
        for (var i = 0; i < oLi.length; i++) {
            oLi[i].onclick = (function (i){
                return function(){
                        alert(i)
                    };
            })(i);
        }
    }   
    

    三、闭包需要注意的地方?

    3.1 IE下会引发内存泄露

    内存泄露会导致浏览器内存占用过高,内存中的变量无法变量,必须关闭浏览器,关闭这个网页也无法清除

    window.onload = function(){
        var oDiv = document.getElementById("div1");
        oDiv.onclick = function(){
            alert(oDiv.id); // 由于内部引用了oDiv,导致oDiv无法释放
        }
    }  
    

    可以通过onunload事件,将onclick取消,来释放oDiv

    window.onload = function(){
        var oDiv = document.getElementById("div1");
        oDiv.onclick = function(){
            alert(oDiv.id); // 由于内部引用了oDiv,导致oDiv无法释放
        }
        
        window.onunload = function(){
            oDiv.onclick = null;
        }
    }  
    

    或者:

    window.onload = function(){
        var oDiv = document.getElementById("div1");
        var id = oDiv.id;
        oDiv.onclick = function(){
            alert(id); // 由于内部引用了oDiv,导致oDiv无法释放
        }
        oDiv = null;
    }  
    
  • 相关阅读:
    第二周作业
    7-2 求最大值及其下标
    第十一周作业
    第九周编程总结
    第八周作业
    第七周作业
    第六周作业
    第五周作业
    第4周作业
    第三周作业
  • 原文地址:https://www.cnblogs.com/linhp/p/6084953.html
Copyright © 2011-2022 走看看