2011-12-12 16 views
5

mi sono imbattuto nel seguente schema quando si guarda attraverso il codice sorgente di SlickGrid:Qual è la ragione per questo modello di chiamata immediata di JavaScript?

(function ($) { 
    var SlickEditor = { 

    TextCellEditor: function (args) { 
     ... 
    }, 

    LongTextCellEditor: function (args) { 
     ... 
    } 
    }; 

    $.extend(window, SlickEditor); 

})(jQuery); 

Se ho capito bene, si sta usando invocazione immediato per definire vari oggetti funzione e poi unirle in namespace globale.

Quindi potrei definire le mie funzioni globalmente in questo modo e avrebbe lo stesso effetto, giusto?

function TextCellEditor (args) { 
    ... 
} 

function LongTextCellEditor (args) { 
    ... 
} 

L'unica differenza che posso vedere è che nella prima versione, è possibile utilizzare il $ abbreviata per fare riferimento all'oggetto jQuery. Oltre a ciò il risultato sarebbe identico in entrambi i casi.

Mi piacerebbe sapere se mi manca qualcosa. Forse c'è un'altra buona ragione per fare le cose in questo modo?

UPDATE: Si noti che l'utilizzo di questo modello di chiamata immediata consente l'utilizzo di variabili private dichiarate nella funzione anonima. Ma non ci sono variabili dichiarate in questo caso e le funzioni vengono comunque iniettate nell'ambito globale. Quindi mi piacerebbe ancora sapere se c'è una vera differenza.

Alcune risposte hanno sottolineato che la referenziazione di variabili locali è molto più rapida rispetto al riferimento a variabili globali. Rimane valido anche se faccio riferimento a $ dal costruttore TextCellEditor(). $ non è realmente locale a TextCellEditor() poiché è definito nell'ambito della funzione anonimo esterna.

Tutti i commenti sono graditi.

+0

... L'esempio illustrato inserisce una singola variabile in ambito globale. Inietti più funzioni in ambito globale. C'è un'enorme differenza tra una variabile globale e molte variabili globali – Raynos

+0

@Raynos: Entrambi gli esempi iniettano le stesse funzioni in ambito globale. la chiamata '$ .extend()' estende l'oggetto window con tutte le proprietà di 'SlickEditor' (in questo caso le due funzioni del costruttore). Questo è il punto della mia domanda: qual è la differenza? – njr101

+0

oh aspetta, non mi ero reso conto che l'autore di SlickEditor era un idiota e ha iniettato tutte le funzioni in ambito globale. Questo è un modello anti, entrambi i campioni di codice sono una cattiva pratica. – Raynos

risposta

3

La differenza è che si sta creando un ambito locale per variabili private quando si utilizza una funzione auto-invocante come quella che si è mostrata.

Questo tipo di funzione di auto invocazione è di solito chiamato una chiusura ed è la base di molti modelli di javascript, come il modello di modulo: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth

Si può leggere di più su javascript scoping qui: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

La ragione di passando il vairable jQuery in è 2 volte:

1: è più comoda per chiamare tramite $ e da quando è stato passato come una variabile locale possiamo essere sicuri che $ non è qualcosa d'altro

2: è più veloce - le variabili locali sono molto più veloce di accedere e lavorare con più variabili globali

Come esempio dare un'occhiata al seguente pezzo di codice:

var public_and_global=true; 

(function(){ 
    var private_and_local = true; 

    function local_func() { 
    //can use private_and_local as well as public_and_global 
    } 

})(); 

function global_func() { 
    //can only use public_and_global 
} 
+0

Non ci sono variabili "private" – Raynos

+0

Grazie Martin. Capisco il problema della scoping/closure. Ma poiché non ci sono variabili nella funzione anonima, ho pensato che questo avrebbe significato che il risultato netto sarebbe stato lo stesso in entrambi i miei esempi. Non ero a conoscenza della differenza di prestazioni. Il vantaggio prestazionale si applica all'utilizzo di '$' all'interno del costruttore di TextCellEditor? Non sono sicuro perché '$' non è realmente locale per quella funzione, ma locale per la funzione anonima nell'ambito esterno. – njr101

+0

Hai ragione, nell'esempio esatto il risultato netto è molto vicino a essere lo stesso, eccetto che le due funzioni nel primo esempio sono namespace nello spazio dei nomi 'SlickEditor'. Meteo o meno la loro è una differenza di prestazioni nello scenario esatto è qualcosa che lascerò al tuo test :) –

0

Sì, sarebbe hanno il stesso effetto, nella maggior parte dei casi. Ma in questo modo è bello perché puoi sempre usare la stenografia, ma anche perché non ci saranno variabili che ingombrano lo spazio dei nomi globale.Dire che ho questa estensione, per generare ID univoci:

var UID = (new Date).getTime(); 
$.uniqueID = function() { return (UID++).toString(16); } 

Questo sarebbe solo di lavoro, ma se ho impostato UID più tardi, probabilmente in un altro script, questa funzione non funzionerà più. E bene, non si può mai essere troppo sicuri della disponibilità di $ che è anche una buona ragione.

Le variabili definite all'interno di una funzione non saranno presenti nello spazio dei nomi globale.

1

Ognuno avvolge l'intero codice in un IIFE.

Questo perché tutti utilizzano variabili locali e nessuno utilizza variabili globali.

Se la tecnica dell'architettura modulare è "Inject modules into global scope", i moduli verranno iniettati in ambito globale dall'IFE.

+0

+1 per influenzare gli sviluppatori con * "Tutti lo stanno facendo ..." * pressione tra pari. – RightSaidFred

+0

Grazie per il consiglio.Sono a conoscenza delle migliori pratiche in questa situazione, ma speravo in una risposta alla mia domanda specifica. – njr101

0

Sicuramente, quello che ha detto Martin. Inoltre:

Quindi potrei definire le mie funzioni globalmente in questo modo e sarebbe avere lo stesso effetto, giusto?

No. Queste funzioni non terminano nello spazio dei nomi globale. Vengono creati in un ambito locale e quindi i riferimenti a questi vengono assegnati a jQuery. Nulla è aggiunto all'ambito globale.

Sebbene lo snippet che hai mostrato non lo dimostri, è possibile definire alcuni dati privati, oltre alle funzioni, all'interno di tale ambito, ad esempio, stringhe fisse o tabelle di ricerca, o qualsiasi altro dato ausiliario di cui quei metodi potrebbero necessitare, e le funzioni avranno accesso a tali dati, e tuttavia tali dati non saranno accessibili a nessun altro codice (analogo a "privato" in OO), né i dati inquinano lo spazio dei nomi globale.

+0

Non capisco questo. Sicuramente la riga '$ .extend (window, SlickEditor);' estenderà l'oggetto globale (nel caso di un browser è l'oggetto window). Queste funzioni saranno disponibili per qualsiasi riga di codice, senza dipendere da jQuery. – njr101

Problemi correlati