2013-04-03 11 views
8

Jaki jest cel zewnętrznych nawiasów zewnętrznych w poniższej funkcji zamykania JavaScript? Powiedziano mi w innych postach, że nie są one bezwzględnie konieczne, ale są konwencją, która wyjaśnia, że ​​wynik funkcji jest przekazywany, a nie sama funkcja. Poniższy cytat z http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html , jednak konflikty. Który jest poprawny?Przeznaczenie zewnętrznego dodatkowego nawiasu na funkcję zamykania JavaScriptu

Zwróć uwagę na() wokół anonimowej funkcji. Jest to wymagane przez język , ponieważ instrukcje rozpoczynające się od funkcji tokenu to zawsze uważane za deklaracje funkcji. Włączenie() tworzy zamiast tego wyrażenie funkcji .

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

Można również poprzedzić je nieważne lub operatorem arytmetycznym. –

+1

@Jack. Proszę wyjaśnij. – user1032531

+1

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

Odpowiedz

5

myślę, że różne silniki mają różne sposoby interpretowania

function(){...}();

więc najbardziej popularnym i akceptowanym sposobem, aby było jasne, do wszystkich silników, jest grupą kodu w zdanie wtrącone.

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

W tym samym czasie, co sprawia, że ​​cytowany bardzo interesujący punkt. Wyrażenie funkcja może pójść:

var f = function() {...}

Podczas gdy deklaracja funkcji wygląda następująco:

function f() {...}

Widzisz jak łatwo/wygodne dla parser odróżnić patrząc na pierwszą znak?

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

Ale to nie ma sensu za (natychmiast-wywoływanego) funkcja do deklaracji funkcji (nie będzie ponownie wykorzystane, nie chcesz mieć to wydobywanych, lub w przestrzeń nazw itp.), więc dodanie niewinnych nawiasów jest dobrym sposobem na wskazanie, że jest to wyrażenie funkcyjne.

+0

Czasami jest to wymagane, a czasem nie w oparciu o dany silnik, i powinienem to robić przez cały czas? – user1032531

+1

Tak. To bardzo silna konwencja. Powinieneś prawdopodobnie robić to cały czas ... chyba że znajdziesz jakiś inny popularny sposób, żeby wyjaśnić silnikowi i chcesz to osiągnąć. – ktm5124

+0

FF powoduje błąd składni s bez niego. – user1032531

1

Są one konieczne, ponieważ parser idzie w trybie deklaracji funkcji, gdy widzi

function 

w kontekście oświadczenie.

Po tokenie function oczekuje nazwy dla funkcji, ponieważ deklaracja funkcji musi zawierać nazwę funkcji. Zamiast tego zamiast nazwy widzi (, więc jest to błąd składniowy.

Myślę, że może się cofnąć i jednoznacznie traktować to jako wyrażenie funkcji, ale tak nie jest.


var module = XXX

W powyższym XXX w kontekście wyrażenie jeśli function pojawia się tam, że są traktowane jako początku ekspresji funkcyjnego. Wyrażenia funkcyjne nie muszą mieć nazwy dla funkcji, więc nie jest to błąd składniowy, aby ( pojawił się zaraz po function.

Więc można napisać:

var module = function(){}(); 

lecz nie

function(){}() 

Można skorzystać z wielu sztuczek, aby powyższe wyrażenia:

(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 jest w kontekście wypowiedzi, ponieważ jest on zamknięty za pomocą nawiasu lub podąża za operatorem jednoargumentowym, a więc dowolną funkcją podstawiony przez XXX jest wyrażeniem funkcji.

3

Dodatkowe otaczające nawiasy disambiguate wyrażenie funkcji z deklaracji funkcji regularnych.

Choć dodatkowe nawiasy są standardową praktyką, to samo można osiągnąć w ten sposób zamiast:

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

Albo nawet:

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

Chociaż z tych dwóch alternatyw, I preferujemy notację void, ponieważ w większości przypadków nie zwracamy uwagi na wartość zwracaną natychmiastowego wywołania.

innych miejscach, gdzie nie są wymagane nawiasy jest, gdy oczekuje się wyrazem:

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

Przede wszystkim muszę wyjaśnić:

(function() { 

}()); 

odpowiada za

(function() { 

})(); 

, a także dla (Backbone.js go używa)

(function(){ 

}).call(this); 

Po drugie, jeśli zamierzasz używać go w ten sposób, to nie jest to funkcja anonimowa/zamknięta. Natychmiast jego -Wykonano wyrażenie Funkcja

będzie ona działać jako zamknięcie (bo nie będzie natychmiast-wywoływany) jeśli przypisać jej kontekst zwrócony do zmiennej. Jest to przydatne, jeśli potrzebujesz klasy statycznej (gdy właściwości i metody mogą być dostępne bez tworzenia instancji).Na przykład:

var stuff = (function(){ 

    // AGAIN: its not an IIFE in this case 

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

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


stuff.foo(); //Alerts Jeeez 

Jaki jest cel zewnętrznych dodatkowych nawiasach na poniższym funkcji JavaScript zamknięcia?

Cel nie jest zwyczajny i dość dziwny - chodzi tylko o argumenty funkcyjne. Na przykład

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

    alert(arguments.length); // 0! 

})(); 

ale jeśli chcemy przekazać je do tego zewnętrznych nawiasach

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

    alert(arguments.length); // 2 

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

Świetne wyjaśnienie. Chciałbym móc głosować więcej. Sądzę, że inne odpowiedzi lepiej spełniły moje konkretne pytanie, ale to wyjaśniło moją większą tajemnicę. '(function (c, d) {console.log (a, b, c, d);} (a, b));' wyświetli a, b, a, b. Dostaję to dzięki tobie! Dzięki – user1032531

Powiązane problemy