1. 程式人生 > >【JavaScript基礎筆記】模組化、立即執行函式應用、閉包應用

【JavaScript基礎筆記】模組化、立即執行函式應用、閉包應用

模組化:為了提高JS程式碼的長期可讀性,易維護性,將JS程式碼根據其對應的功能塊區分成不同的JS檔案,並將其包裹在立即執行函式內,從而使其中的變數設定為區域性變數,不會造成不同模組的變數汙染。

 

立即執行函式
在 Javascript 中,圓括號()是一種運算子,跟在函式名之後,表示呼叫該函式。比如,print()就表示呼叫print函式。
有時,我們需要在定義函式之後,立即呼叫該函式。這時,你不能在函式的定義之後加上圓括號,這會產生語法錯誤。

產生這個錯誤的原因是,function這個關鍵字即可以當作語句,也可以當作表示式。

為了避免解析上的歧義,JavaScript 引擎規定,如果function關鍵字出現在行首,一律解釋成語句。因此,JavaScript引擎看到行首是function關鍵字之後,認為這一段都是函式的定義,不應該以圓括號結尾,所以就報錯了。
解決方法就是不要讓function出現在行首,讓引擎將其理解成一個表示式。最簡單的處理,就是將其放在一個圓括號裡面。

上面兩種寫法都是以圓括號開頭,引擎就會認為後面跟的是一個表示式,而不是函式定義語句,所以就避免了錯誤。這就叫做“立即呼叫的函式表示式”(Immediately-Invoked Function Expression),簡稱 IIFE。
注意,上面兩種寫法最後的分號都是必須的。如果省略分號,遇到連著兩個 IIFE,可能就會報錯。
推而廣之,任何讓直譯器以表示式來處理函式定義的方法,都能產生同樣的效果,比如下面三種寫法。

甚至像下面這樣寫,也是可以的。

通常情況下,只對匿名函式使用這種“立即執行的函式表示式”。它的目的有兩個:一是不必為函式命名,避免了汙染全域性變數;二是 IIFE 內部形成了一個單獨的作用域,可以封裝一些外部無法讀取的私有變數。

 

如何使用立即執行函式

ES 5 裡面,只有函式有區域性變數,於是我們宣告一個 function xxx,然後 xxx.call() 這個時候 xxx 是全域性變數(全域性函式)。

所以我們不能給這個函式名字 function(){}.call() 但是 Chrome 報錯,語法錯誤。

經過嘗試得到幾種方法可以不報錯:

  1. !function(){}.call()  【我們不在乎這個匿名函式的返回值,所以加個 ! 取反沒關係】
  2. (function(){}).call()  xxx  (function(){}).call()  【如果(fn).call前誤寫xxx,會導致意外函式執行,不推薦】
  3. frank192837192463981273912873098127912378.call() 【冗長繁雜,不推薦】

 

閉包的應用

當我們通過模組化我們的JS程式碼檔案後,立即執行函式使得我們的模組檔案無法被外部訪問。

那麼,如果遇到A模組需要引用B模組的變數時,我們可以通過將xxx變數新增到window的屬性下,然後在另一個模組中也同樣將window.xxx的地址賦值給xxx,這樣就可實現模組資料溝通。

如果需要隱藏資料的細節,實現訪問控制,那麼我們還可以通過閉包,使得B模組可以操作由A模組裡的變數構造的函式,但無法訪問A模組裡的變數資料

!function(){
    var dinner = {
        main: noodle;
        guests : 2
    }
    window.guestsIncrease = function(){
        numeber += 1
        return number
    }
}.call()

 

當然我們也可以不使用window全域性變數,通過自己設定的區域性變數實現。本質上都是一樣的將這個匿名函式的引用通過閉包儲存起來,然後立即執行。

 

var accessor = function(){
    var dinner = {
        main: noodle;
        guests : 2
    }
    return function(){
        numeber += 1
        return number
    }
}

// B模組
var increase = accessor.call()
increase.call()