Day 19:函數定義 (Function Definition) 的 100 種寫法
標題只是嚇嚇你而已 (毆)。
(Source: 網路圖片)
函數 (Function) 是程式編寫非常重要的一環。
大多數常見程式語言的函數定義都是一套語法格式,頂多加一些修飾子的變化 (例如 public
、private
、static
),整體語法還是同一套的格式。
但 JavaScript 裡定義函數的語法花樣可多了,不同寫法所定義出來的函數物件 (Function Object) 也各有些微差異,叫人眼花撩亂。
如果沒有特別需求,太多不同寫法只會造成開發團隊 Coding Convention 一致性的困擾,甚至造成不必要的 Bug 風險。
本篇文章試著去統整已知的 JavaScript 函數寫法,比較彼此差異。
宣告函數在語法上有 4 種方式
宣告式 (Function Declarations)
匿名表達式 (Function Expressions w/o Function Name)
具名表達式 (Function Expressions w/ Function Name)
建構子式 (Function Constructor)
ES6 多了第 5 種 —— Arrow Function。
宣告式 (Function Declarations)
特點:
最普遍標準的寫法。
使用
function
關鍵字作函數的宣告和定義。具有 Hoisting 效果,會提升到 Scope 頂端。
執行結果:
關於 Hoisting 可參考 Day10 文章。
匿名表達式 (Function Expressions w/o Function Name)
特點:
先宣告一個變數,再定義一個函數內容放到該變數裡。
此方式定義的函數實際上是匿名函數 (a function without a name),只是將函數定義的主體存在某個變數裡。
變數名稱不等於函數名稱。
不具 Hoisting 效果。
執行結果:
具名表達式 (Function Expressions w/ Function Name)
特點:
和「匿名表達式」十分相似,只差在定義函數內容時,有給予一個函數名稱。
定義的函數印出來會有函數名稱(不等於變數名稱)。
但無法直接透過該函數名稱呼叫,所以該函數名稱基本上沒用。
不具 Hoisting 效果。
沒有使用的必要。
為何無法直接透過函數名稱呼叫?
目前理解: 因為該函數不算正式宣告於此 Scope,對此 Scope 來說不存在該名稱,所以無法直接透過函數名稱呼叫。
執行結果:
建構子式 (Function Constructor)
W3Schools:
With a built-in JavaScript function constructor called
Function()
。
特點:
先宣告一個變數,再用 JavaScript 內建的函數建構子
Function()
去定義函數內容,放到該變數裡。用
Function()
定義的函數自動被給予函數名稱anonymous
,但和「具名表達式」一樣,都無法直接透過該函數名稱呼叫。不具 Hoisting 效果。
沒有使用的必要。
執行結果:
總結
函數的宣告和定義在語法上有 4 種寫法:
# | 寫法 | Hoisting | 備註 |
1 | 宣告式 | Y | |
2 | 匿名表達式 | N | |
3 | 具名表達式 | N | 沒有必要使用 |
4 | 建構子式 | N | 沒有必要使用 |
這 4 種寫法定義時的寫法不太一樣,但在使用上除了些許細節 (例如 Hoisting),大致上其實差不多。
其中 1 和 2 是最普遍的寫法;3 和 4 如果沒有特殊需求,沒必要使用。
ES6 多了第 5 種函數寫法:Arrow Function。
由於 Arrow Function 不只是語法有所不同,還增加了不少使用上的特性,明天的文章將另外專門對 Arrow Function 作介紹。
References
Last updated