閉包(closure)

閉包是面試中常問到的一個問題,但是這種概念性的東西有時候寫的時候不自覺的就能使上,但是陳述的時候又會表達的含混不清。記錄之以備忘。

函數字面量定義在其他函數中時,它不僅可以訪問自己的參數和變量,同時它也能訪問把它嵌套在其中的父函數的參數和變量。通過函數字面量創建的函數對象包含一個連接到外部上下文的鏈接。這就成爲閉包

錯誤之源在於JavaScript中沒有C,JAVA語言中的塊級作用域括(在一堆花括號中的一組語句)其中的變量在代碼塊之外是不可見的,定義在代碼塊中的變量執行結束後會被釋放掉。而JavaScript有函數作用域,定義在其中的參數和變量在函數外部是不可見的,而在函數內部任何位置定義的變量,在該函數內部任何地方都可見。

舉個栗子,我們店給string增加一個deentityify的方法,任務是尋找字符串中的html字符實體,換成對應的字符。這就需要保存字符實體的名字和他們對應的字符。但我們在那保存這個對象呢?全局變量是魔鬼。我們可以把它定義在函數的內部,但是會帶來運行時的損耗,因爲每次執行該函數的時候該字面變量都會被求一次值。理想的方式是把它放入一個閉包。

String.prototype.deentityify=function(){
    var entity={
        quot:'"',
        lt  :'<',
        gt  :'>'
    };
    //返回要定義的deentityify方法
    return function(){
        //查找‘&’開頭和‘;’結束的字符串。如果這些字符串可以在字符串實體中找到,
        //那麼就將該字符實體替換爲映射中的值。
        return this.replace(/&([^&;]+;/g,function(a,b){
            var r=entity[b];
            return typeof r==='string' ? r: a;
        }   
    }
}();

閉包的一般形式爲:一個定義了私有變量和函數的函數。利用閉包創建可以訪問私有變量和函數的特權函數,最後返回這個特權函數。私有變量的狀態可以得以保存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章