Come funziona questa syntax JavaScript / JQuery: (function (window, undefined) {}) (window)?

Hai mai dato un’occhiata sotto il cofano al codice sorgente di JQuery 1.4 e notato come è incapsulato nel modo seguente:

(function( window, undefined ) { //All the JQuery code here ... })(window); 

Ho letto un articolo su JavaScript Namespacing e un altro chiamato ” An Important Pair of Parens “, quindi so qualcosa su cosa sta succedendo qui.

Ma non ho mai visto prima questa particolare syntax. Cosa c’è che undefined è undefined lì? E perché la window deve essere passata e poi apparire di nuovo alla fine?

L’indefinito è una variabile normale e può essere modificato semplicemente con undefined = "new value"; . Quindi jQuery crea una variabile “non definita” locale che è VERAMENTE indefinita.

La variabile della finestra è resa locale per motivi di prestazioni. Perché quando JavaScript cerca una variabile, prima passa attraverso le variabili locali fino a trovare il nome della variabile. Quando non viene trovato, JavaScript passa attraverso il prossimo ambito ecc. Fino a quando non filtra attraverso le variabili globali. Quindi se la variabile della finestra è resa locale, JavaScript può cercarlo più velocemente. Ulteriori informazioni: Velocizza il tuo JavaScript – Nicholas C. Zakas

Non definito

Dichiarando un valore non undefined come argomento ma non passando mai un valore, esso assicura che sia sempre indefinito, in quanto è semplicemente una variabile nell’ambito globale che può essere sovrascritta. Ciò rende a === undefined un’alternativa sicura a typeof a == 'undefined' , che salva alcuni caratteri. Rende anche il codice più minettimile, poiché undefined può essere abbreviato per esempio, salvando alcuni caratteri in più.

Finestra

Passare la window come argomento mantiene una copia nell’ambito locale, che influenza le prestazioni: http://jsperf.com/short-scope . Tutti gli accessi alla window ora dovranno viaggiare di un livello in meno rispetto alla catena dell’ambito. Come con undefined , una copia locale consente nuovamente una minificazione più aggressiva.


Nota a margine:

Sebbene questa potrebbe non essere stata l’intenzione degli sviluppatori di jQuery, la window passaggio consente di integrare più facilmente la libreria negli ambienti Javascript lato server, ad esempio node.js , in cui non esiste alcun object window globale. In una situazione del genere, è necessario modificare solo una riga per sostituire l’object window con un altro. Nel caso di jQuery, è ansible creare e inoltrare un object window fittizio ai fini dello scraping HTML (una libreria come jsdom può farlo).

Altri hanno spiegato undefined . undefined è come una variabile globale che può essere ridefinita a qualsiasi valore. Questa tecnica è di impedire che tutti i controlli indefiniti si spezzino se qualcuno ha scritto, da qualche parte, undefined = 10 . Un argomento che non viene mai passato è garantito come reale undefined indipendentemente dal valore della variabile undefined .

Il motivo per passare la finestra può essere illustrato con il seguente esempio.

 (function() { console.log(window); ... ... ... var window = 10; })(); 

Cosa registra la console? Il valore dell’object window giusto? Sbagliato! 10? Sbagliato! Registra undefined . L’interprete Javascript (o compilatore JIT) lo riscrive in questo modo –

 (function() { var window; //and every other var in this function console.log(window); ... ... ... window = 10; })(); 

Tuttavia, se si ottiene la variabile della window come argomento, non c’è var e quindi nessuna sorpresa.

Non so se jQuery lo stia facendo, ma se stai ridefinendo la variabile locale della window ovunque nella tua funzione, per qualsiasi motivo, è una buona idea prenderla a prestito da un ambito globale.

window viene passata in questo modo nel caso in cui qualcuno decida di ridefinire l’object finestra in IE, presumo lo stesso per undefined , nel caso in cui venga nuovamente assegnato in un secondo momento.

La window in alto in quello script sta solo nominando l’argomento “window”, un argomento che è più locale del riferimento alla window globale e che cosa utilizzerà il codice all’interno di questa chiusura. La window alla fine sta in realtà specificando cosa passare per il primo argomento, in questo caso il significato attuale della window … la speranza è che non hai rovinato la window prima che ciò accada.

Questo può essere più facile da pensare mostrando il caso più tipico usato in jQuery, la gestione dei plugin .noConflict() , quindi per la maggior parte del codice puoi ancora usare $ , anche se questo significa qualcosa di diverso da jQuery al di fuori di questo ambito:

 (function($) { //inside here, $ == jQuery, it was passed as the first argument })(jQuery); 

Testato con 1000000 iterazioni. Questo tipo di localizzazione non ha avuto alcun effetto sulle prestazioni. Nemmeno un solo millisecondo in 1000000 iterazioni. Questo è semplicemente inutile.