首頁 >web前端 >js教程 >js立即執行函數: (function ( ){})( ) 與 (function ( ){}( )) 有什麼區別?_javascript技巧

js立即執行函數: (function ( ){})( ) 與 (function ( ){}( )) 有什麼區別?_javascript技巧

WBOY
WBOY原創
2016-05-16 15:31:191058瀏覽

沒有差別。

你需要明白 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 有幫助,有興趣的話可以繼續深入閱讀:http://www.jb51 .net/article/75090.htm

方式一,呼叫函數,得到回傳值。強制函數直接量執行再回傳一個引用,引用在去呼叫執行
方式二,呼叫函數,得到返回值。強制運算子使函數呼叫執行
(function(){})(); 是 把函數當作表達式解析,然後執行解析後的函數
相當於 var a = function(){}; a(); a得到的是函數
(function(){}()); 是把函數表達式和執行當作語句直接執行、
相當於 var a = function(){}(); a得到的是結果
最終結果是一樣的、
()只是起了 自執行的作用
和 () 一樣的還有很多
如 function (){}
這個等於 (function (){}) 一般用(function (){}) 還有個作用,就是 避免全域變數

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn