摘要: (function() {})();和(function(){}());的區別
Javascript中有2個語法都與function關鍵字有關,分別是:
函數定義:function FunctionName(FormalParameterList) { FunctionBody }
函數表達式:function [FunctionName](FormalParameterList) { FunctionBody }
從語法的定義上看,這兩者幾乎是一模一樣的(唯一的區別是函數表達式可以省略函數名稱),那么就解釋器而言,當遇到這個結構的語句時,判定為函數表達式還是函數定義呢?
就javascript的語法而言,如果一條語句是以function關鍵字開始,那么這段會被判定為函數定義。而函數定義是不能被立即執行的,這無疑會導致語法的錯誤(SyntaxError),因此就必須有一個辦法,使解析器可以將之識別為函數表達式。
前面已經說到,解析器識別函數定義的條件是以function關鍵字開始,那么自然,只要在function關鍵字的前面有任何其他的元素,就會從函數定義轉變為函數表達式,以下方法都是可以的,這個大家都知道:
~function() {}();
!function() {}();
void function() {}();
但是這幾個方法都有一個特點,就是看起來很別扭,所以現在為止,以括號包裹成了比較公認的方案。
回到正題,括號包裹同樣有2個方式:(function() {})();和(function(){}());
他們的共通點是:都有括號。而括號在javascript中有2種作用:確立運算優先級,以及分組運算符,從代碼上看,顯然沒有進行數學或邏輯運算,因此我認為這里的括號屬於分組運算符。
根據標准,分組運算符的作用是:
Return the result of evaluating Expression. This may be of type Reference.
返回評估括號中的表達式的結果。結果可能是Reference類型。
拋開像Reference類型這種詞匯,這里的一個關鍵詞應當是“ 評估 ”,但是關於分組運算符,又有一個很重要的下文:
This algorithm does not apply GetValue to the result of evaluating Expression.
這個算法不會對估算的結果使用GetValue。
有很多專用的名詞,看起來確實復雜,簡而言之,使用括號運算符本身不會讓括號中的代碼立即執行,只有當括號包含的這個“分組”參與其他運算時,才會執行。因此,(function(){})()這個語句,其實是首先用分組運算符評估了一個函數表達式,隨后參與“函數調用”。而(function(){}())這個語句,則是用分組運算符評估了一個函數調用,隨后由於語句的結束而被執行。
