1、什麼是閉包? 閉包就是指有權訪問另一個函數作用域中變數的函數,通俗點講閉包就是能夠讀取其他函數變數的函數。常見的構造方法,是在一個函數內部定義另外一個函數。內部函數可以引用外層的參數和變數;參數和變數不會被垃圾回收機制回收。除非用立即執行函數來解決。所以閉包的特性: (1)函數內再嵌套函數; ( ...
1、什麼是閉包?
閉包就是指有權訪問另一個函數作用域中變數的函數,通俗點講閉包就是能夠讀取其他函數變數的函數。常見的構造方法,是在一個函數內部定義另外一個函數。內部函數可以引用外層的參數和變數;參數和變數不會被垃圾回收機制回收。除非用立即執行函數來解決。所以閉包的特性:
(1)函數內再嵌套函數;
(2)內部函數可以引用外層的參數和變數;
(3)參數和變數不會被垃圾回收機制回收。
1 function fn1() {
2 var a = 1 ;
3 function fn2() {
4 alert(a);
5 }
6 return fn2;
7 }
8
9 var result = fn1();
10 result(); //1
上述函數fn2就是一個閉包,我們可以通過返回fn2獲取到fn1中的變數。
2、閉包的用途
(1)通過閉包去訪問函數內部的變數;
(2)使某些變數常駐記憶體。
1 //沒有閉包情況下變數a的情況
2 function add() {
3 var a = 1;
4 a++;
5 alert(a);
6 }
7 add(); //2
8 add(); //2
9
10 //有閉包的方式下
11 function add2() {
12 var a = 1;
13 function fn() {
14 a++;
15 alert(a);
16 }
17 return fn;
18 }
19 var result = add2();
20 result(); //2
21 result(); //3
在有閉包的情況下,result()的兩次輸出分別是2、3,這說明aad2中的a變數一直在記憶體當中,並沒有因為add2的調用後被垃圾回收機制回收(garbage collection)。
為什麼會產生這樣的情況?這是因為add2是fn的父親函數,而在全局環境當中,fn其實是被賦給了全局變數result的,而result只會在全局環境執行完所有代碼之後才會被回收,所以就導致了fn常駐記憶體,而fn的存在又依賴於父親函數add2,所以add2在被調用之後也不會被GC(垃圾回收機制)回收,也始終存在於記憶體當中。
3、閉包可能會引發的問題
由於IE9之前的版本對JSript對象和COM對象使用了不同的垃圾回收機制,所以閉包在IE9之前的版本中會導致記憶體泄漏問題。具體來說就是,如果閉包中保存著一個HTML元素,那麼這個元素將無法被銷毀,直到退出程式或關閉瀏覽器。
1 <script>
2 window.onload = function () {
3 var oBox = document.getElementById('box');
4
5 oBox.onclick = function () {
6 alert(oBox.id);
7 }
8 };
9 </script>
像上述的情況下就發生了記憶體泄漏,因為在閉包中創建了一個迴圈引用。可以通過以下方法得到解決:
1 <script>
2 window.onload = function () {
3 var oBox = document.getElementById('box');
4
5 oBox.onclick = function () {
6 alert(oBox.id);
7 };
8
9 //方法一
10 window.onunload = function () {
11 oBox.onclick = null;
12 }
13 };
14
15 //方法二
16 window.onload = function () {
17 var oBox = document.getElementById('box');
18 var id = oBox.id;
19
20 oBox.onclick = function () {
21 alert(id);
22 };
23
24 oBox = null;
25 };
26
27 </script>