引言:全局變量是魔鬼,我們最好不要與它打交道;
使用閉包的好處是讓函數(shù)自我管理歧蒋,通過現(xiàn)有函數(shù)生成(return)新的更加實用的函數(shù)(閉包返回匿名函數(shù))。
現(xiàn)在我們需要寫一個函數(shù)州既,它的功能是將字符串中的HTML實體(例如<>)轉換為相應的字符谜洽,輸入是一個字符串,輸出是一個新的字符串吴叶。我們可以很容易想到阐虚,創(chuàng)建一個字符映射表,根據(jù)正則表達式依次替換就可以了蚌卤。思路很簡單实束,我們嘗試一下奥秆。
方案一
var entity = {
quot: '"',
lt:'<',
gt:'>'
};
var deentityify = function(str){
return str.replace(/&([^&;]+);/g,function(a,b){
var r = entity[b];
return typeof r ==='string' ? r : a;
});
};
deentityify('>');//output >
在全局作用域內(nèi)生成了一個映射表entity
,再在全局作用域內(nèi)聲明了函數(shù)實體咸灿,最后調(diào)用它构订,雖然能達到目的,但是的確不是好的結構風格避矢,畢竟放那么多變量在全局作用域內(nèi)悼瘾,到最后是非常難以維護的。
方案二
var deentityify1 = function(str){
//在函數(shù)內(nèi)部聲明了entity映射表审胸,確保外界無法訪問亥宿,避免污染
var entity = {
quot: '"',
lt:'<',
gt:'>'
};
return str.replace(/&([^&;]+);/g,function(a,b){
var r = entity[b];
return typeof r ==='string' ? r : a;
});
};
方案二將entity移動到了函數(shù)體內(nèi)部,這樣做可以避免一部分污染砂沛,可是我們仔細想一想烫扼,在這個函數(shù)調(diào)用結束之后,entity沒有被任何變量所引用碍庵,所以它將會被回收映企,問題來了,在我大量調(diào)用這個函數(shù)時怎抛,將會伴隨著entity的多次創(chuàng)建和回收卑吭。
方案三-使用閉包
var deentityify2 = function(){
var entity = {
quot: '"',
lt:'<',
gt:'>'
};
return function(str){
if(str !== undefined){
return str.replace(/&([^&;]+);/g,function(a,b){
var r = entity[b];
return typeof r ==='string' ? r : a;
});
}else{
return '請輸入?yún)?shù)';
}
};
}();//deentityify2函數(shù)實際上得到的是這個匿名函數(shù)的返回值
在創(chuàng)建這個函數(shù)時,加上()
調(diào)用操作符來立即調(diào)用马绝,本來entity應該在這個函數(shù)結束后被回收的豆赏,因為閉包的產(chǎn)生,使一個全局函數(shù)deentityify2通過引用一個匿名函數(shù)從而引用了entity富稻,導致它并不會被回收掷邦,entity作為私有變量,只能通過特權函數(shù)deentityify2去訪問椭赋,實現(xiàn)了信息隱藏抚岗。