函數表達式和函數聲明

在ECMAScript中,創建函數的最常用的兩個方法是函數表達式和函數聲明,兩者期間的區別是有點暈,因為ECMA規范只明確了一點:函數聲明必須帶有標示符(Identifier)(就是大家常說的函數名稱),而函數表達式則可以省略這個標示符:

函數聲明:

function函數名稱(參數:可選){函數體}

函數表達式:

function函數名稱(可選)(參數:可選){函數體}

所以,可以看出,如果不聲明函數名稱,它肯定是表達式,可如果聲明了函數名稱的話,如何判斷是函數聲明還是函數表達式呢?ECMAScript是通過上下文來區分的,如果function foo(){}是作為賦值表達式的一部分的話,那它就是一個函數表達式,如果function foo(){}被包含在一個函數體內,或者位于程序的最頂部的話,那它就是一個函數聲明。


表達式和聲明存在著十分微妙的差別,首先,函數聲明會在任何表達式被解析和求值之前先被解析和求值,即使你的聲明在代碼的最后一行,它也會在同作用域內第一個表達式之前被解析/求值,參考如下例子,函數fn是在alert之后聲明的,但是在alert執行的時候,fn已經有定義了:


函數聲明的實際規則如下:

函數聲明只能出現在程序函數體內。從句法上講,它們 不能出現在Block(塊)({ ... })中,例如不能出現在 if、while 或 for 語句中。因為 Block(塊) 中只能包含Statement語句, 而不能包含函數聲明這樣的源元素。另一方面,仔細看一看規則也會發現,唯一可能讓表達式出現在Block(塊)中情形,就是讓它作為表達式語句的一部分。但是,規范明確規定了表達式語句不能以關鍵字function開頭。而這實際上就是說,函數表達式同樣也不能出現在Statement語句或Block(塊)中(因為Block(塊)就是由Statement語句構成的)。

提到命名函數表達式,理所當然,就是它得有名字,前面的例子var bar = function foo(){};就是一個有效的命名函數表達式,但有一點需要記住:這個名字只在新定義的函數作用域內有效,因為規范規定了標示符不能在外圍的作用域內有效:


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容