【Javascript 拾遗之三】Closure 闭包
Closure 閉包
1、閉包的定義
-離散數(shù)學(xué)
一個關(guān)系不具有自反, 對稱, 傳遞這3種基本性質(zhì)之一,但均可以通過對該關(guān)系的擴(kuò)充(在關(guān)系中增添序偶),使擴(kuò)充后的關(guān)系具有這種性質(zhì),這種包含該關(guān)系的最小擴(kuò)充稱為該關(guān)系關(guān)于這種性質(zhì)的閉包.下面給出閉包的定義:
設(shè)R是X上的關(guān)系,R的自反(或?qū)ΨQ,傳遞)閉包R1是這樣的:包含R(或R包含于R1)的自反(或?qū)ΨQ,傳遞)關(guān)系,對任意的自反(或對稱,傳遞) 關(guān)系S,如果R包含于S,則必有R1包含于S.
滿足的條件:
設(shè)R是非空集合A上的關(guān)系, R的自反(對稱或傳遞)閉包是A上的關(guān)系R' ,滿足 (1) R'是自反的(或對稱的,或傳遞的) (2) ?R?R'
????? (3)對A上任何包含[R的自反(或?qū)ΨQ的,或傳遞的)]關(guān)系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高級程序設(shè)計中提到:Javascript閉包就是在函數(shù)中定義函數(shù),實現(xiàn)的功能就是在函數(shù)外部也能訪問函數(shù)內(nèi)部的局部變量。
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這個玩意就是閉包,他可以在函數(shù)外部訪問函數(shù)內(nèi)部的變量,是不是很神奇?
其實沒啥神奇的,代碼示例中closure()執(zhí)行了closure這個方法,返回了一個匿名函數(shù),這是一個沒有執(zhí)行的匿名函數(shù),然后通過()函數(shù)運算符,執(zhí)行了closure中的alertA這個方法。alertA返回了私有變量a的值,我們稱在子函數(shù)中使用父函數(shù)的局部變量的結(jié)構(gòu)為閉包結(jié)構(gòu)。
?
2、閉包的應(yīng)用
-模塊化代碼
我們再看一個例子
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返回了一個數(shù)組,該數(shù)組指向多個定義的匿名函數(shù)生成的對象,這個閉包可以通過數(shù)組不同的索引來調(diào)用,相當(dāng)于一個多元的閉包,在模塊化開發(fā)時候可以使用這個結(jié)構(gòu)。
3、閉包的缺點
-內(nèi)存泄露
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();代碼實例中是一個閉包結(jié)構(gòu),修改部分用//modified ->標(biāo)注了,未修改前,在IE瀏覽器中,由于IE的內(nèi)存回收機(jī)制,element.onclick 引用的匿名函數(shù)中調(diào)用了element.id致使element對象得不到釋放,一直存貯在內(nèi)存中,如果這個函數(shù)被調(diào)用多次,那么內(nèi)存中的element引用會越來越多,導(dǎo)致內(nèi)存泄露。此例是指在引用Html element時候,放在閉包內(nèi)對象得不到釋放而導(dǎo)致的。因此,在使用閉包的同時要注意內(nèi)存的釋放。
4、總結(jié)
?本文通過幾個簡單的例子介紹了Javascript的閉包及其應(yīng)用,實際開發(fā)中由于閉包長期內(nèi)存需要代碼釋放和比較難理解的語法,所以在沒有必要的情況下不建議使用閉包。
5、參考資料
Javascript 高級程序設(shè)計第二版
http://cise.sdust.edu.cn/lssx/7StressResolve/cha3/36.htm
?
轉(zhuǎn)載于:https://www.cnblogs.com/keaixiaoye/p/4184367.html
總結(jié)
以上是生活随笔為你收集整理的【Javascript 拾遗之三】Closure 闭包的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 周进度总结表(一)
- 下一篇: iOS 获取手机信息