標籤:
摘要: (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(){}())這個語句,則是用分組運算子評估了一個函數調用,隨後由於語句的結束而被執行。
JS中函數定義和函數運算式的區別