(function(){}())與(function(){})()的區別

直接進入正題。請說出 immediately-invoked function expression(IIFE)的如下兩種寫法的區別: express

(function () {
  // code here
})();

(function () {
  // code here
}());

嘛,從效果上來講,正如StackOverflow(SO)上的網友說的:「It genuinely doesn’t matter, so do whatever you prefer.」。好吧囧,不要拍磚,其實在語法層面上仍是有區別的,如下配合引用SO上的CMS(這是網友id,不是那啥……)的描述來說講。 app

首先要明白如下寫法是語法錯誤的: 函數

function() {
 // code here
} ();

編譯器會認爲該表達式是函數聲明,因爲在‘function’與‘()’之間找不到函數名稱而拋出語法錯誤。爲了可以實現immediately-invoked,因而有了在討論的兩種寫法。 學習

對於第一種寫法,經過將函數表達式的調用用括號包起來,使編譯器理解括號內的代碼是表達式而不是聲明,從而可以正確解析: ui

CallExpression
                |         |
       FunctionExpression |
                |         |
                V         V
    (function() {       }());
    ^                      ^
    |--PrimaryExpression --|

對於第二種寫法,其實也是經過括號將函數表達式包起來使編譯器明白該函數表達式不是聲明從而正確編譯,而後馬上使用‘()’來調用這個函數: code

PrimaryExpression
                |
         FunctionExpression
                |
                V
    (function() {       })();
    ^                      ^
    |--  CallExpression  --|

能夠看出,兩種寫法的關鍵點就是經過將表達式放在‘()’中,使編譯器可以正確識別其爲函數表達式而不是聲明。因而,其實下面的寫法也都是能夠的: 對象

-function(){}();
+function(){}();
!function(){}();
...

呃……這些寫法確實非常有趣,並且也比本文討論的兩種寫法少了一個字符……但存在很大的缺陷。考慮下面的語句: 編譯器

var obj = !function() {
    return {};
}();

很顯然,無論函數裏返回了什麼,最後obj變量保存的都是true布爾值。而使用括號包住的方式則能正確返回Object對象。 it

ok,相信看官看到這裏應該已經明白IIFE的寫法了(若是你說這真是個很無聊的問題……其實我也是這麼想XD~重要的是學習的過程啊親)。那還有一個問題就是,使用哪一種寫法是比較推薦的呢?jQuery推薦第一種寫法,而老道Crockford則推薦第二種。如下是老道這樣推薦的緣由: io

「[...] and again, I’m wrapping the whole function and the invocation in parens. as a sign to the reader that there is something bigger going on than just an assignment of a function. There are some people who will put the golden paren. around the function and not around the whole invocation — that doesn’t make sense to me because what we are trying to tell the user is: ‘Look at the whole thing’, and putting parentheses around just part of it, I think, is counter-productive, so I think the whole thing needs to be wrapped in parens.」 — Douglas Crockford.

大意是說:使用括號將函數與調用符一塊兒包含起來,是爲了告訴讀者這是一個總體,而只包含函數表達式的寫法對他來講沒有意義。

可是我我的是比較習慣第一種寫法的,將函數表達式與調用符經過括號分隔開,在我看來是更清晰的調用。嘛,仁者見仁智者見智,想怎麼用就怎麼用吧,這個問題上沒什麼好辯論的:)

最後是給看到文章末尾的人的福利哈哈。偶然看到的函數調用方式:

(a || b) && (a || b)()
// 等價於:
// a ? a() : (b && b());

雖然沒想到什麼場景下會有這樣的調用,但以爲想到這個的人真有才…

相關文章
相關標籤/搜索