天天看點

自調用匿名函數(匿名閉包)解析與調用

打開jQuery源碼,首先你會看到這樣的代碼結構:

這是一個自調用匿名函數。什麼東東呢?在第一個括号内,建立一個匿名函數;第二個括号,立即執行

為什麼要建立這樣一個“自調用匿名函數”呢?

通過定義一個匿名函數,建立了一個“私有”的命名空間,該命名空間的變量和方法,不會破壞全局的命名空間。這點非常有用也是一個JS架構必須支援的功能,jQuery被應用在成千上萬的JavaScript程式中,必須確定jQuery建立的變量不能和導入他的程式所使用的變量發生沖突。

接下來看看在 自調用匿名函數 中都實作了什麼功能,按照代碼順序排列:

匿名函數從文法上叫函數直接量,JavaScript文法需要包圍匿名函數的括号,事實上自調用匿名函數有兩種寫法:

 經常使用的方法如下格式:

為什麼要傳入window呢?

通過傳入window變量,使得window由全局變量變為局部變量,當在jQuery代碼塊中通路window時,不需要将作用域鍊回退到頂層作用域,這樣可以更快的通路window;這還不是關鍵所在,更重要的是,将window作為參數傳入,可以在壓縮代碼時進行優化,看看jquery-1.6.1.min.js: (function(a,b){})(window); // window 被優化為 a 

通過以上的介紹,我們大概了解通過()可以使得一個函數表達式立即執行。

匿名函數作為一個“容器”,“容器”内部可以通路外部的變量,而外部環境不能通路“容器”内部的變量,

是以 ( function(){…} )() 内部定義的變量不會和外部的變量發生沖突,俗稱“匿名包裹器”或“命名空間”。

通俗的講,()就是用來求值的,是以這個()任何時候都不能為空,因為它是要計算的。函數解析它隻會解析到 {}為止,不會解析到 ()的。

把表達式放在()中會傳回表達式的值;

把函數放在()中會傳回函數本身;(function(){}());

如果()緊跟在函數後面,就是表示在調用函數,即對函數求值:(function(){})();

代碼在運作過程中,會優先解析 【巳聲明的函數】;

而函數表達式是當執行到它時,才會解析;

匿名函數是不會單獨寫的,是以它的執行是需要其它函數的調用,通常看到的匿名函數,都是當作參數被傳遞的。而立即執行函數它本身就是個匿名函數,

立即執行函數配合閉包,在子產品化中的應用,其中要明白幾個點:

1、要在函數體後面加括号就能立即調用,則這個函數必須是函數表達式,不能是函數聲明;

2、立即執行函數可以當作是一個私有作用域,作用域内部可以通路外部的變量,而外部環境是不能通路作用域内部的變量的,是以,立即執行函數是一個封閉的作用域,不會和外部作用域起沖突。

JQuery使用的就是這種方法,将JQuery代碼包裹在( function (window,undefined){…jquery代碼…} (window)中,在全局作用域中調用JQuery代碼時,可以達到保護JQuery内部變量的作用。

3、Module模式,是自執行函數的進階模式,可以非常友善的在各個匿名閉包中以全局對象調用閉包函數。有興趣可以檢視:http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html Module 模式為:

  a.建立一個立即調用的匿名函數表達式

  b.return一個變量,其中這個變量裡包含你要暴露的東西

  c.傳回的這個變量将指派給window

/******上面就是關于自調用匿名函數的解析,那麼這樣的函數它是怎麼被調用的呢?*******/

/******下面是關于全局變量的調用,也就是匿名閉包函數的調用*******/

Module 模式,也就是匿名閉包的建立與調用:

window(或者是任意一個全局對象)作為一個帶有多個屬性的全局對象,也可以把window當成一個參數,以對象的方式,在其它函數中實作調用。用下面的例子說明:

下面是一個标準的Module模式,通過匿名函數的傳回值來傳回這個全局變量:

在一些大型項目裡,将一個功能分離成多個檔案是非常重要的,因為可以多人合作易于開發。再回頭看看上面的全局參數導入例子,我們能否把blogModule自身傳進去呢?答案是肯定的,我們先将blogModule傳進去,添加一個函數屬性,然後再傳回就達到了我們所說的目的:

那麼,多個自執行函數間是怎麼調用的呢?

如果第二個函數想調用 全局變量為C中的 對象呢?要怎麼寫?

再舉個例子,同樣的,不同自執行閉包函數間的調用方法:

是以 匿名閉包的調用規則是這樣的,立即執行(最後一個括号) (window),如果把window作為一個參數進行傳遞,那麼就把它以對象的方式,在其它函數中實作全局調用。

如果有錯誤,請大家指正,謝謝!

繼續閱讀