(1)使用 function 關鍵字聲明一個函數,再指定一個函數名,叫函數聲明。javascript
(2)【注意】JavaScript引擎規定,若是function關鍵字出如今行首,一概解釋成函數聲明語句html
(1)使用 function 關鍵字聲明一個函數,函數名稱可被省略,此種狀況下的函數是 匿名函數(anonymous)。 函數名稱只是函數體中的一個本地變量。java
(2)將匿名函數賦予一個變量,叫函數表達式,這是最多見的函數表達式語法形式。web
(1)下面是匿名函數的一個例子(函數沒有名字)。express
(2)也能夠在定義時爲函數命名。segmentfault
(3)命名函數表達式的好處是當咱們遇到錯誤時,堆棧跟蹤會顯示函數名,容易尋找錯誤。設計模式
(4)能夠看到,上面的兩個例子都不以function開頭。不以function開頭的函數語句就是函數表達式定義。安全
(1)但有時須要在定義函數以後,當即調用該函數(函數只使用一次)。這種函數就叫作當即執行函數,全稱爲當即調用函數表達式IIFE(Imdiately Invoked Function Expression)閉包
當即調用函數表達式(IIFE)是一個在定義時就會當即執行的 JavaScript 函數。
(1)這是一個被稱爲 自執行匿名函數 的設計模式,主要包含兩部分。第一部分是包圍在 圓括號運算符() 裏的一個匿名函數。函數
(2)第二部分再一次使用 () 建立了一個當即執行函數表達式,JavaScript 引擎到此將直接執行函數。
(1)【最經常使用的兩種辦法】
(2)【其餘寫法】
(1)不管什麼時候,給當即執行函數 加上括號 是個好習慣。
(2)經過以上的介紹,咱們大概瞭解經過()可使得一個函數表達式當即執行。
(3)有的時候,咱們實際上不須要使用()使之變成一個函數表達式,啥意思?好比下面這行代碼,其實不加上()也不會保錯。
(4)可是咱們依然推薦加上()。
(5)爲何?由於咱們在閱讀代碼的時候,若是 function 內部代碼量龐大,咱們不得不滾動到最後去查看 function(){} 後 是否帶有(),用來肯定 i 的值,並判斷是 function 仍是 function內部的返回值。因此爲了代碼的可讀性,請儘可能加上(),不管是否已是表達式。
(1)IIFE 中的匿名函數擁有 獨立的詞法做用域。這不只避免了外界訪問此 IIFE 中的變量,並且又不會污染全局做用域。(另外一種說法 【構造一個函數做用域,防止污染全局變量】)
(2)JavaScript 沒用私有做用域的概念,若是是在多人開發的項目,你在全局或局部做用域中聲明的變量,可能會被其餘人不當心用同名的變量給 覆蓋,根據JavaScript 函數做用域鏈的特性,使用這種技術能夠模仿一個私有做用域,匿名函數做爲一個「容器」,「容器」內部能夠訪問外部的變量,而外部環境不能訪問「容器」內部的變量,因此 ( function(){…} )() 內部定義的變量不會和外部的變量發生衝突,俗稱「匿名包裹器」或「命名空間」。
(3)【注意】將 IIFE 分配給一個變量,不是存儲 IIFE 自己,而是存儲 IIFE 執行後返回的結果。
接下來用一個需求實現來更直觀地說明IIFE的用途。假設有一個需求,每次調用函數,都返回加1的一個數字(數字初始值爲0)
【1】全局變量
通常狀況下,咱們會使用全局變量來保存該數字狀態
【2】自定義屬性
但上面的方法中,變量a實際上只和add函數相關,卻聲明爲全局變量,不太合適
將變量a更改成函數的自定義屬性更爲恰當
【3】IIFE
其實這樣作,仍是有問題。有些代碼可能會無心中將add.count重置
使用IIFE把計數器變量保存爲私有變量更安全,同時也能夠減小對全局空間的污染
參考文章
深刻理解JavaScript系列(4):當即調用的函數表達式 湯姆大叔