JavaScript 學習筆記— —閉包(二)

來源:互聯網
上載者:User

標籤:

閉包有三個特性:

1.函數嵌套函數2.函數內部可以引用外部的參數和變數3.參數和變數不會被記憶體回收機制回收

閉包的定義及其優缺點

閉包 是指有權訪問另一個函數範圍中的變數的函數,建立閉包的最常見的方式就是在一個函數內建立另一個函數,通過另一個函數訪問這個函數的局部變數

使用閉包有一個優點,也是它的缺點,就是可以把局部變數駐留在記憶體中,可以避免使用全域變數。全域變數在每個模組都可調用,這勢必將是災難性的。(所以推薦使用私人的,封裝的局部變數。)

一般函數執行完畢後,局部使用中的物件就被銷毀,記憶體中僅僅儲存全域範圍。但閉包的情況不同!

 function aaa() {            var a = 1;            return function(){           alert(a++)          };          }                 var fun = aaa();          fun();// 1 執行後 a++,,然後a還在~          fun();// 2           fun = null;//a被回收!!

閉包會使變數始終儲存在記憶體中,如果不當使用會增大記憶體消耗。

javascript的記憶體回收原理

(1)、在javascript中,如果一個對象不再被引用,那麼這個對象就會被GC回收;
(2)、如果兩個對象互相引用,而不再被第3者所引用,那麼這兩個互相引用的對象也會被回收。

使用閉包的好處

那麼使用閉包有什麼好處呢?使用閉包的好處是:

1.希望一個變數長期駐紮在記憶體中2.避免全域變數的汙染3.私人成員的存在
一、全域變數的累加
<script>var a = 1;function abc(){        a++;        alert(a);}abc();              //2abc();            //3</script>
二、局部變數
<script>function abc(){        var a = 1;        a++;        alert(a);}abc();                       //2abc();                    //2</script>

那麼怎麼才能做到變數a既是局部變數又可以累加呢?

三、局部變數的累加
<script>function outer(){        var x=10;        return function(){             //函數嵌套函數                x++;                alert(x);        }}var y = outer();              //外部函數賦給變數y;y();                 //y函數調用一次,結果為11,相當於outer()();y();                //y函數調用第二次,結果為12,實現了累加</script>
函式宣告與函數運算式

在js中我們可以通過關鍵字function來聲明一個函數:

<script>function abc(){        alert(123);}abc();</script>我們也可以通過一個"()"來將這個聲明變成一個運算式:<script>(function (){        alert(123);})();                   //然後通過()直接調用前面的運算式即可,因此函數可以不必寫名字;</script>
四、模組化代碼,減少全域變數的汙染
<script>var abc = (function(){      //abc為外部匿名函數的傳回值        var a = 1;        return function(){                a++;                alert(a);        }})();abc();    //2 ;調用一次abc函數,其實是調用裡面內建函式的傳回值    abc();    //3</script>
五、私人成員的存在
<script>var aaa = (function(){        var a = 1;        function bbb(){                a++;                alert(a);        }        function ccc(){                a++;                alert(a);        }        return {                b:bbb,             //json結構                c:ccc        }})();aaa.b();     //2aaa.c()      //3</script>
六.使用匿名函數實現累加
//使用匿名函數實現局部變數駐留記憶體中,從而實現累加<script type="text/javascript"> function box(){     var age = 100;     return function(){          //匿名函數          age++;          return age;     }; } var b = box();alert(b());alert(b());    //即alert(box()());alert(b());alert(b);            //     function () {                        //   age++;                       // return age;                      //       }b = null;  //解除引用,等待記憶體回收</script>

過度使用閉包會導致效能的下降。函數裡放匿名函數,則產生了閉包

七、在迴圈中直接找到對應元素的索引
  <!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" xml:lang="en">    <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++){                    aLi[i].onclick = function(){        //當點擊時for迴圈已經結束                    alert(i);                    };            }    }    </script>    </head>    <body>            <ul>                    <li>123</li>                    <li>456</li>                    <li>789</li>                    <li>010</li>            </ul>    </body>    </html>
八、使用閉包改寫上面代碼
 <!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" xml:lang="en">    <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);            }            };    </script>    </head>    <body>            <ul>                    <li>123</li>                    <li>456</li>                    <li>789</li>            </ul>    </body>    </html>
九.記憶體泄露問題

由於IEjs對象和DOM對象使用不同的垃圾收集方法,因此閉包在IE中會導致記憶體泄露問題,也就是無法銷毀駐留在記憶體中的元素

function closure(){    var oDiv = document.getElementById(‘oDiv‘);//oDiv用完之後一直駐留在記憶體中    oDiv.onclick = function () {        alert(‘oDiv.innerHTML‘);//這裡用oDiv導致記憶體泄露    };}closure();//最後應將oDiv解除引用來避免記憶體泄露function closure(){    var oDiv = document.getElementById(‘oDiv‘);    var test = oDiv.innerHTML;    oDiv.onclick = function () {        alert(test);    };    oDiv = null;}

 

參考:http://segmentfault.com/a/1190000000652891

JavaScript 學習筆記— —閉包(二)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.