js當即執行函數: (function ( ){...})( ) 與 (function ( ){...}( )) 有區別?

在SF上看到這樣一個問題,我以爲問得很好,因此弄成文章收集了。瀏覽器

沒有區別。函數

你須要明白 IIFE 的原理,我簡單說一下:this

function foo() {...}     // 這是定義,Declaration;定義只是讓解釋器知道其存在,可是不會運行。

foo();                   // 這是語句,Statement;解釋器遇到語句是會運行它的。

IIFE 並不是必須,傳統一點能夠這麼寫:code

function foo() {...}
foo();

那麼爲何要 IIFE?對象

  1. 傳統的方法囉嗦,定義和執行分開寫;作用域

  2. 傳統的方法直接污染全局命名空間(瀏覽器裏的 global 對象,如 window)開發

因而,開發者們想找一個能夠解決以上問題的寫法。那麼像下面這麼寫行不行呢?字符串

function foo(...){}();

固然是不能,可是爲何呢?由於 function foo(...){} 這個部分只是一個聲明,對於解釋器來講,就好像你寫了一個字符串 "function foo(...){}",它須要使用解析函數,好比eval() 來執行它才能夠。因此把 () 直接放在聲明後面是不會執行,這是錯誤的語法。io

如何把它變得正確?提及來也簡單,只要把 聲明 變成 表達式(Expression) 就能夠了。function

實際上轉變表達式的辦法仍是不少的,最多見的辦法是把函數聲明用一對 () 包裹起來,因而就變成了:

(function foo() {...})    // 這裏是故意換行,實際上能夠和下面的括號連起來
();

這就等價於:

var foo = function () {...};    // 這就不是定義,而是表達式了。
foo();

可是以前咱們說不行的那個寫法,其實也能夠直接用括號包起來,這也是一種等價的表達式:

(function foo(){...}());

因此答案是:木有區別~

另外,剛纔說過轉變表達式的方式不少,的確還有不少別的寫法,好比:

!function foo() {...}();

或者

+function foo() {...}();

這些均可以。

我我的挺偏心用 void 來轉變表達式,由於此關鍵字不會有返回值。不過這一點真的沒有什麼要緊的,就當我「龜毛」好了……

void function () {
    // 這裏是真正須要的代碼
}();

OK,所謂不去污染全局命名空間,是由於 IIFE 建立了一個新的函數做用域,你真正的業務代碼被封裝在其中,天然就不會觸碰到全局對象了。若是你須要全局對象,那就 pass 給 IIFE:

void function (global) {
    // 在這裏,global 就是全局對象了
}(this)    // 在瀏覽器裏,this 就是 window 對象
相關文章
相關標籤/搜索