【Javascript 拾遺之三】Closure 閉包

提及閉包這個概念,實際上是離散數學中的一種定義,而很程序員們耳熟能詳但不必定能說清楚它的含義和用途。本文先簡單地介紹下離散數學中的閉包,而後再探討一下Javascript語言中的閉包是如何建立和應用的。

Closure 閉包

一、閉包的定義

-離散數學

一個關係不具備自反, 對稱, 傳遞這3種基本性質之一,但都可以經過對該關係的擴充(在關係中增添序偶),使擴充後的關係具備這種性質,這種包含該關係的最小擴充稱爲該關係關於這種性質的閉包.

下面給出閉包的定義:

設R是X上的關係,R的自反(或對稱,傳遞)閉包R1是這樣的:包含R(或R包含於R1)的自反(或對稱,傳遞)關係,對任意的自反(對稱,傳遞) 關係S,若是R包含於S,則必有R1包含於S.

知足的條件:
  設R是非空集合A上的關係, R的自反(對稱或傳遞)閉包是A上的關係R' ,知足
  (1) R'是自反的(對稱的,或傳遞的)
  (2)
 R⊆R'

      (3)對A上任何包含[R的自反(或對稱的,或傳遞的)]關係R" 有R'⊆R"
 
     
 
 
 
  

   r(R) - R的自反閉包, reflexivity
程序員

   s(R) - R的對稱閉包, symmetry
數組

   t(R) - R的傳遞閉包。 transmit
瀏覽器



R={<a,b>,<b,a>,<b,c>,<c,d>}

r(R)={<a,a>,<b,b>,<c,c>,<d,d>,<a,b>,<b,a>,<b,c>,<c,d>}

s(R)={<a,b>,<b,a>,<b,c>,<c,b>,<c,d>,<d,c>}

t(R)={<a,b>,<a,b>,<a,c>,<a,d>,<b,c>,<b,d>,<b,a>,<b,b>,<c,d>}

-Javascript

在Javascript高級程序設計中提到:Javascript閉包就是在函數中定義函數,實現的功能就是在函數外部也能訪問函數內部的局部變量。閉包

1 var closure = function(){
2     var a = 100;
3     var alertA = function(){
4         return(a);
5     }
6     return alertA;
7 }
8 console.log(closure()());  //100

這個玩意就是閉包,他能夠在函數外部訪問函數內部的變量,是否是很神奇?模塊化

其實沒啥神奇的,代碼示例中closure()執行了closure這個方法,返回了一個匿名函數,這是一個沒有執行的匿名函數,而後經過()函數運算符,執行了closure中的alertA這個方法。alertA返回了私有變量a的值,咱們稱在子函數中使用父函數的局部變量的結構爲閉包結構函數

 

二、閉包的應用

-模塊化代碼

咱們再看一個例子flex

 1 function createFunctions(){  2 var result = new Array();  3  4 for(var i = 0; i < 10; i++){  5 result[i] = function(num){  6 return function(){  7 return num;  8  }  9  }(i); 10  } 11 return result; 12 } 13 14 var funcs = createFunctions(); 15 for(var i = 0; i < funcs.length; i++){ 16  console.log(funcs[i]()); 17 }

 

代碼示例中createFunctions返回了一個數組,該數組指向多個定義的匿名函數生成的對象,這個閉包能夠經過數組不一樣的索引來調用,至關於一個多元的閉包,在模塊化開發時候可使用這個結構。spa

三、閉包的缺點

-內存泄露

 1 function assignHandler(){
 2     var element = document.getElementById('someElement');
 3     var id = element.id
 4     element.onclick = function(){
 5         alert(id); // modified -> someElement save as local variable
 6         alert(element.id); //error element is null
 7     }
 8     element = null;  // modified -> release mem invoked by element
 9     return function(){
10         console.log(element); // null
11     }
12 }
13 var m = assignHandler();
14 m();

代碼實例中是一個閉包結構,修改部分用//modified ->標註了,未修改前,在IE瀏覽器中,因爲IE的內存回收機制,element.onclick 引用的匿名函數中調用了element.id導致element對象得不到釋放,一直存貯在內存中,若是這個函數被調用屢次,那麼內存中的element引用會愈來愈多,致使內存泄露。此例是指在引用Html element時候,放在閉包內對象得不到釋放而致使的。所以,在使用閉包的同時要注意內存的釋放。設計

四、總結

 本文經過幾個簡單的例子介紹了Javascript的閉包及其應用,實際開發中因爲閉包長期內存須要代碼釋放和比較難理解的語法,因此在沒有必要的狀況下不建議使用閉包。code

五、參考資料

Javascript 高級程序設計第二版

http://cise.sdust.edu.cn/lssx/7StressResolve/cha3/36.htm

相關文章
相關標籤/搜索