js立即執行函式: (function ( ){})( ) 與 (function ( ){}( )) 有什麼區別?
這篇文章主要介紹了js立即執行函式: (function ( ){})( ) 與 (function ( ){}( )) 有什麼區別,需要的朋友可以參考下
沒有區別。
你需要明白 IIFE 的原理,我簡單說一下:
複製程式碼 程式碼如下:
function foo() {...} // 這是定義,Declaration;定義只是讓直譯器知道其存在,但是不會執行。 foo(); // 這是語句,Statement;直譯器遇到語句是會執行它的。 IIFE 並非必須,傳統一點可以這麼寫:
複製程式碼 程式碼如下:
function foo() {...}
foo();
那麼為什麼要 IIFE?
1.傳統的方法囉嗦,定義和執行分開寫;
2.傳統的方法直接汙染全域性名稱空間(瀏覽器裡的 global 物件,如 window)
於是,開發者們想找一個可以解決以上問題的寫法。那麼像下面這麼寫行不行呢?
function foo(...){}();
當然是不能,但是為什麼呢?因為 function foo(...){} 這個部分只是一個宣告,對於直譯器來說,就好像你寫了一個字串 "function foo(...){}",它需要使用解析函式,比如 eval() 來執行它才可以。所以把 () 直接放在聲明後面是不會執行,這是錯誤的語法。
如何把它變得正確?說起來也簡單,只要把 宣告 變成 表示式(Expression) 就可以了。
實際上轉變表示式的辦法還是很多的,最常見的辦法是把函式宣告用一對 () 包裹起來,於是就變成了:
複製程式碼 程式碼如下:
(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 物件
我在這裡寫過一個系列,其中一篇講作用域和命名提升的,裡面的知識點對理解 IIFE 有幫助,有興趣的話可以繼續深入閱讀://www.jb51.net/article/75090.htm(別人的不是我的,我是搬運工)
方式一,呼叫函式,得到返回值。強制函式直接量執行再返回一個引用,引用在去呼叫執行
方式二,呼叫函式,得到返回值。強制運算子使函式呼叫執行
(function(){})(); 是 把函式當作表示式解析,然後執行解析後的函式
相當於 var a = function(){}; a(); a得到的是函式
(function(){}()); 是把函式表示式和執行當作語句直接執行、
相當於 var a = function(){}(); a得到的是結果
最終結果是一樣的、
()只是起了 自執行的作用
和 () 一樣的還有很多
比如 +function (){}
這個等於 (function (){}) 一般用(function (){}) 還有個作用,就是 避免全域性變數