JavaScript是我目前最常使用的語言,但對於它的特性我一直沒有深入研究,只是在使用的時候隱約感覺到它有自己的特別之處,在這裡就來探討JavaScript的函式為什麼First-class function,它需要具備什麼特性以及在JavaScript中是怎麼運用First-class function的這些特性。
First-class citizen
在講First-class function前,我們先來聊聊First-class citizen。
在程式語言中,First-class citizen是指某個實體可以執行所有的操作,這寫操作包括下面這幾項:
- 可以當作參數
- 可以當作函式的回傳值
- 可以被修改
- 可以指派給變數
現在知道定義了,但是實際上在程式語言上到底什麼是First-class citizen還是不太清楚,我們來看些例子吧。
舉例
下面的兩個例子分別探討在C語言中的兩個實體Integer及Array是不是First-class citizen。
Integer
首先來看看Integer在C中是不是First-class citizen。
1 |
|
上面這個例子顯示了Integer在C中的確是First-class citizen,它滿足了所有的條件。
Array
再來我們來看Array在C中是否有滿足First-class citizen的條件。
1 |
|
這裡可以看到Array並不是First-class citizen,因在C中Array只能用指標的方式傳入函式內,也就是第一個元素的記憶體位置,所以它其實不能當作參數,所以他並不是First-class citizen。
First-class function
來到本篇的重點,其實First-class function這個特性其實就是: 一個程式語言將函式賦予First-class citizen的特性,實際來說有下面幾個特性:
- Higher-order functions
- Nested functions
- Anonymous functions
- Non-local variables
我們依序來說明上述的這些特性。
Higher-order functions
Higher-order functions有兩個特性:
- 將一個或多個函式當作參數
- 回傳結果可以是函式
上面的特性以下面的例子說明:
1 | // Higher-order function |
這個例子我們可以知道JavaScript的確可以將函式當作參數及回傳值。
Nested functions
顧名思義就是可以在函式被其他函式宣告,我們來看下面的例子:
1 | // 2. Nested function |
可以看到innerFunc
是在outterFunc
中宣告的。
Anonymous functions
匿名函式是可以不用替函式命名就可以宣告函式。
1 | // 3. Anonymous function |
上述範例回傳Hello Anonymous
的函式並沒有名稱,是一個匿名函式。
Non-local variable
在函式中可以取得不是全域也不是本區的變數,請看下面的例子:
1 | // 4. Non-local variable |
outter
這個參數既不是在全域也不是innerFunc中的區域變數,它是在Closure時帶進來的。
代碼
附上CODEPEN的代碼供參考。
See the Pen Why does JS have First-class function? by Peter Chen (@peterhpchen) on CodePen.
簡報
結語
由上述的特性及其JavaScript的範例來證明Function確實是First-class functions,其實函數式語言一定會有First-class function,所以屬於函數式語言的JavaScript理所應當會有First-class function。