Posizione delle parentesi per l’esecuzione automatica di funzioni JavaScript anonime?

Recentemente ho confrontato la versione corrente di json2.js con la versione che avevo nel mio progetto e ho notato una differenza nel modo in cui l’espressione della funzione è stata creata ed eseguita autonomamente.

Il codice utilizzato per racchiudere una funzione anonima tra parentesi e quindi eseguirla,

(function () { // code here })(); 

ma ora racchiude la funzione auto-eseguita tra parentesi.

 (function () { // code here }()); 

C’è un commento di CMS nella risposta accettata di Explain syntax della funzione anonima incapsulata di JavaScript che “both: (function(){})(); e (function(){}()); sono validi. ”

Mi stavo chiedendo quale sia la differenza? Il primo occupa la memoria abbandonando una funzione globale anonima? Dove dovrebbe essere localizzata la parentesi?

Sono praticamente uguali.

Il primo avvolge le parentesi attorno a una funzione per renderlo un’espressione valida e invocarlo. Il risultato dell’espressione è indefinito.

Il secondo esegue la funzione e le parentesi attorno al richiamo automatico lo rendono un’espressione valida. Inoltre valuta a indefinito.

Non penso che esista un modo “giusto” per farlo, poiché il risultato dell’espressione è lo stesso.

 > function(){}() SyntaxError: Unexpected token ( > (function(){})() undefined > (function(){return 'foo'})() "foo" > (function(){ return 'foo'}()) "foo" 

In tal caso non importa. Si sta richiamando un’espressione che si risolve in una funzione nella prima definizione e che definisce e richiama immediatamente una funzione nel secondo esempio. Sono simili perché l’espressione di funzione nel primo esempio è solo la definizione della funzione.

Ci sono altri casi più ovviamente utili per invocare espressioni che risolvono le funzioni:

 (foo || bar)() 

Non c’è alcuna differenza oltre la syntax.

Per quanto riguarda le tue preoccupazioni sul secondo metodo di farlo:

Prendere in considerazione:

(function namedfunc () { ... }())

namedfunc sarà ancora nella portata globale anche se hai fornito il nome. Lo stesso vale per le funzioni anonime. L’unico modo per ottenerlo in tale ambito sarebbe assegnarlo a una variabile all’interno del paren.

 ((namedfunc = function namedfunc () { ... })()) 

I parens esterni non sono necessari:

 (namedfunc = function namedfunc () { ... })() 

Ma non volevi comunque quella dichiarazione globale, vero?

Quindi si riduce a:

 (function namedfunc () { ... })() 

E puoi ridurlo ulteriormente: il nome non è necessario poiché non sarà mai usato (a meno che la tua funzione non sia ricorsiva .. e anche in quel caso potresti usare arguments.callee )

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

Questo è il mio modo di pensarci (potrebbe non essere corretto, non ho ancora letto le specifiche ECMAScript). Spero che sia d’aiuto.

La differenza esiste solo perché a Douglas Crockford non piace il primo stile per gli IIFE ! (seriuosamente) Come puoi vedere in questo video !! .

L’unica ragione per l’esistenza del wrapping extra () {in entrambi gli stili} è di aiutare a creare quella sezione di codice Funzione Espressione , perché non è ansible chiamare immediatamente la dichiarazione di funzione . Alcuni script / minify-ers usano solo + ,! , - & ~ invece di troppe parentesi. Come questo:

 +function() { var foo = 'bar'; }(); !function() { var foo = 'bar'; }(); -function() { var foo = 'bar'; }(); ~function() { var foo = 'bar'; }(); 

E tutti questi sono esattamente uguali alle tue alternative. La scelta tra questi casi è completamente autonoma e non fa alcuna differenza. {Quelli con () producono 1 Byte file più grande ;-)}