2013-04-03 49 views
8

以下JavaScript關閉函數外部額外括號的用途是什麼?我在其他文章中被告知他們並不是絕對必要的,但他們是一個約定,以明確函數的結果正在被傳遞,而不是函數本身。然而,從http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html 下面的報價,衝突。哪個是對的?JavaScript關閉函數外部額外括號的用途

注意()周圍的匿名函數。這是由 語言要求的,因爲這與令牌功能開始語句 一直被認爲是函數聲明。包括()會改爲創建一個 函數表達式。

(function() { 
    // ... all vars and functions are in this scope only 
    // still maintains access to all globals 
}()); 
+1

您也可以使用無效或算術運算符前綴它。 –

+1

@Jack。請詳細說明。 – user1032531

+1

http://benalman.com/news/2010/11/immediately-invoked-function-expression/ –

回答

5

我認爲,不同的引擎有解釋

function(){...}();

所以最流行的和接受的方式不同的方式講清楚,所有的引擎,是集團中的代碼括號。

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

與此同時,你引述使得一個非常有趣的一點。函數表達式可能會去:

var f = function() {...}

而函數聲明如下:

function f() {...}

你看它是如何容易/便利解析器分辨通過觀察第一令牌?

IF TOKEN1 EQ "function": FXN DECLARATION 
ELSE: FXN EXPRESSION 

但它是沒有意義的你(立即調用的)函數是一個函數聲明(它不會被重新使用,你不想把它懸掛,或在名稱空間等),因此添加一些無害的括號是指示它是函數表達式的好方法。

+0

那麼,有時需要它,有時候不是基於給定的引擎,我應該一直這樣做? – user1032531

+1

是的。這是一個非常強大的慣例。你應該一直這樣做......除非你找到一些其他流行的方式來清楚引擎,並且想要支持這一點。 – ktm5124

+0

FF在沒有它的情況下會導致s語法錯誤。 – user1032531

1

他們是必要的,因爲解析器雲在函數聲明模式,當它看到

function 

語句的上下文

function標記之後,它期待函數的名稱,因爲函數聲明必須包含該函數的名稱。但代之以(而不是名稱,所以這是一個語法錯誤。

我認爲,它可以回溯並毫不含糊地將其視爲函數表達式,但它不會。


var module = XXX

在上文中,XXX是在表達式上下文,如果function出現在該處,它被當作一個函數表達的開始。函數表達式不必具有 作爲該函數的名稱,因此在function之後出現(並不是語法錯誤。

所以你可以這樣寫:

var module = function(){}(); 

但不是

function(){}() 

您可以使用許多技巧,讓一個表達式以上:

(XXX) 
!XXX 
~XXX 
+XXX 

//This doesn't work however: 
{YYY} //the braces are delimiting a block, and inside block you start in 
     //a statement context 

XXX是在表達方面,因爲它由括號括起來,或者跟隨一個一元運算符,因此是任何函數代替XXX是一個函數表達式。

3

額外的周圍括號歧義從常規函數聲明的函數表達式。

雖然額外的括號是標準的做法,同樣的事情可以做這個,而不是實現:

void function() { 
    // do stuff 
}(); 

或者,甚至:

+function() { 
    // do stuff 
}(); 

雖然,這些兩個選擇,我更喜歡void表示法,因爲在大多數情況下,我們並不真正在意立即調用的返回值。

如果不要求括號其它地方是當一個表達式預計:

setTimeout(function() { 
    return function() { 
     alert('hello'); 
    } 
}(), 1000); 
4

首先,我要澄清:

(function() { 

}()); 

等同於

(function() { 

})(); 

,也爲(Backbone.js的使用它)

(function(){ 

}).call(this); 

第二,如果你要使用這種方式,那麼它不是一個匿名/閉合功能。其立即調用的函數表達式

它會作爲一個封閉的(因爲它不會立即,調用)如果指定其返回的上下文給一個變量。如果你需要一個靜態類(當屬性和方法可以在沒有實例化的情況下訪問),這種方法很有用。例如:

var stuff = (function(){ 

    // AGAIN: its not an IIFE in this case 

    function foo() // <- public method 
    { 
     alert('Jeeez'); 
    } 

    return { 
     foo : foo, 
    } 
})(); 


stuff.foo(); //Alerts Jeeez 

什麼是下面 JavaScript的閉合功能外額外的括號的目的是什麼?

目的是不平常的,很奇怪 - 它所有關於函數的參數。 例如,

(function(window, document){ // <- you see this? 2 "arguments" 

    alert(arguments.length); // 0! 

})(); 

,但如果我們將其傳遞給外部括號

(function(/* So its not for arguments */){ 

    alert(arguments.length); // 2 

})(window, document); // <- Instead we pass arguments here 
+2

很好的解釋。我希望我能投更多。我相信其他答案能夠更好地解決我的具體問題,但這澄清了我的一個更大的謎團。 '(function(c,d){console.log(a,b,c,d);}(a,b));'會顯示a,b,a,b。我感謝你!謝謝 – user1032531