[JavaScript] 立馬執行的立即呼叫函式 (IIFEs)

itsems
itsems_frontend
Published in
7 min readSep 13, 2020
Photo by Boris Stefanik on Unsplash
Outlines:
+ 函式陳述式 & 函式表達式 (Function statement & Function expression)
+ 立即呼叫函式 IIFEs : Immediately Invoked Functions Expressions
+ 為什麼要使用 IIFEs ?

函式陳述式 & 函式表達式 (Function statement & Function expression)

在看 IIFEs 之前,先提一下函式陳述式(function statement),和函式表達式 (function expression)。

函式陳述式(function statement):

函式表達式(function expression):(具名/不具名)

對於表達式和陳述式不太熟悉的話,可以參考這一篇筆記:[JavaScript] Javascript 的表達式 (Expressions)和陳述式 (Statements):一個用說的,一個用做的

立即呼叫函式 IIFEs : Immediately Invoked Functions Expressions

IIFEs,又可以稱為 Self-Executing Anonymous Function (自我執行匿名函式),顧名思義的意思就是立即執行的函式表達式

  • Immediately:立即
  • Invoked:執行
  • Functions Expressions:的函式表達式
ps.這邊的函式表達式,必須使用匿名的函式表達式 (anonymous function expression)

共分為兩種寫法:

  1. 宣告一個變數儲存函式,並在函式結尾加上一個 () ,Javascript 看到他就會馬上執行。
  2. 用一個括弧 (Grouping Operator) 將整個匿名函式括起來。

第一種寫法:將 () 放在函式的結尾

形成原理

以上述的匿名函式表達式稍作修改為例:

如果我們試著印出 myName 這個指向函式的變數,會得到我們的函式:

如果試著執行他:

則會因為沒有帶入變數而出現 undefined,

再將所需參數帶入:

就會回傳出所帶入的參數了。

() 放在函式的結尾

來看看這裡發生了什麼事情,在 function (name){ … } 這段,我創立了一個會回傳 name 的函式,在他的尾端加上 () 表示我呼叫並執行了前面這個函式,這樣定義完即立馬執行的函式,就是所謂的 IIFE 。

而回傳的 name 的值,會賦予變數 myName:

一樣因為沒有帶入任何參數,所以印出的結果為 undefined。

在我剛剛呼叫執行的地方傳入參數的話:

就可以產生一樣的結果。但是需要注意的是我在 console 裡面帶入的 myName 本身已經等於回傳的 emma 這個字串,並不是可以執行的函式,硬是執行 myName 這個字串的話,就會回傳 myName 不是函式的錯誤:

檢查一下,myName 的型別的確已經成為字串

這就是上述的第一種 IIFE 寫法,直接將 () 加在函式後面。

第二種寫法:用一個 Grouping Operator 將函式包起來

第二種寫法是較常見的寫法,也讓你可以不用另外建立變數來儲存 IIFE,

剛剛的例子為:

不要變數,我要函式現場執行並印出 console:

得到錯誤了,為什麼?

因為 Javascript 一旦看到程式的第一個字是 function ,就會反應為這是一個函式陳述式 (function statement),記得上面第一張圖嗎?

函式陳述式 (function statment)

如果是一般的函式陳述式,在宣告並定義完後,是不會自己執行的,而且也需要有名字,所以上面的語法就錯了。為了達到我們的目的,我們需要告訴 Javascript 這是一個函式表達式,這時候就是用上 Grouping operator: () 的時候了。

() 是一個運算子,他只會用在包住表達式的時候,舉例:(3+2)、a+(b*c),並回傳計算結果值,不會拿來包住陳述式如:( if(...) ),所以如果用 Grouping operator 將我們的函式包起來,Javascript 看到程式的第一個字是 ( ,則會視此為表達式,不會辨認為函式陳述式且因為缺乏函式名稱而爆錯。

驗證錯誤是否消失了:

錯誤消失了,可是我沒有帶入參數,是不是應該要有 undefined?

沒有,他只是存在於你的記憶體中,並沒有執行。

要定義後立馬執行他,就像第一種方法一樣,在他的最後面加上 ()

出現了,因為沒有參數的 undefined,帶入參數吧:

這樣就大功告成了,標準的 IIFE 款式。

為什麼要使用 IIFEs ?

你會常常在各大框架中看見 IIFEs 的使用,其中一個最大的原因,就是 IIFEs 可以避免變數汙染到 global 全域,確保不會與其他程式相衝突。

在 IIFEs 中,我印出的 name,會是我帶入的值,與全域變數不相干:

那如果我需要在 IIFE 中使用全域變數,進而修改呢?

在帶入值的地方,多帶入全域就可以了:

在帶入 emma 的前面,我帶入了 window 物件,不一定要是 window 物件,你想要調動的地方都可以,這樣就能把外面的變數帶進來,修改則是:

直接覆寫即可,這樣在外面的全域變數也跟著改變了:

如此的方法,就能調動並改變全域物件了。

--

--

itsems
itsems_frontend

Stay Close to Anything that Makes You Glad You are Alive.