2010-09-20 13 views
7

La mia intuizione è che è una buona idea per incapsulare blocchi di codice in funzioni anonime in questo modo:Devo incapsulare blocchi di funzionalità nelle funzioni JavaScript anonime?

(function() { 
    var aVar; 
    aVar.func = function() { alert('ronk'); }; 
    aVar.mem = 5; 
})(); 

Perché io non avrò bisogno aVar di nuovo, quindi immagino che il garbage collector sarà quindi eliminare aVar quando esce dal campo di applicazione. È giusto? O gli interpreti sono abbastanza intelligenti da vedere che non uso più la variabile e la ripulisco immediatamente? Ci sono motivi come stile o leggibilità che dovrei non utilizzare le funzioni anonime in questo modo?

Inoltre, se nomino la funzione, in questo modo:

var operations = function() { 
    var aVar; 
    aVar.func = function() { alert('ronk'); }; 
    aVar.mem = 5; 
}; 
operations(); 

fa operations quindi necessariamente attaccare intorno fino a quando non esce dallo scope? Oppure l'interprete può dire immediatamente quando non è più necessario?

un esempio migliore

Vorrei anche chiarire che non sto necessariamente parlando di portata globale. Considera un blocco che assomiglia a

(function() { 

    var date = new Date(); // I want to keep this around indefinitely 

    // And even thought date is private, it will be accessible via this HTML node 
    // to other scripts. 
    document.getElementById('someNode').date = date; 

    // This function is private 
    function someFunction() { 
    var someFuncMember; 
    } 

    // I can still call this because I named it. someFunction remains available. 
    // It has a someFuncMember that is instantiated whenever someFunction is 
    // called, but then goes out of scope and is deleted. 
    someFunction(); 

    // This function is anonymous, and its members should go out of scope and be 
    // deleted 
    (function() { 
    var member; 
    })(); // member is immediately deleted 
    // ...and the function is also deleted, right? Because I never assigned it to a 
    // variable. So for performance, this is preferrable to the someFunction 
    // example as long as I don't need to call the code again. 

})(); 

Le mie ipotesi e conclusioni sono corrette? Ogni volta che non riutilizzerò un blocco, non dovrei solo incapsularlo in una funzione, ma incapsularlo in una funzione anonima in modo che la funzione non abbia riferimenti e venga cancellata dopo che è stata chiamata, giusto?

+0

solo curioso, c'è una perdita di memoria? – jebberwocky

risposta

4

Hai ragione che attaccare variabili all'interno di una funzione anonima è una buona pratica per evitare di ingombrare l'oggetto globale.

Per rispondere a queste ultime due domande: È assolutamente impossibile per l'interprete sapere che un oggetto non verrà più utilizzato finché ci sarà un riferimento globalmente visibile ad esso. Per tutti gli interpreti sa, è possibile valutare un codice che dipende da window['aVar'] o window['operation'] in qualsiasi momento.

In sostanza, ricordare due cose:

  1. Fintanto che un oggetto è in giro, nessuno dei suoi slot saranno magicamente liberati senza il tuo dire così.
  2. Le variabili dichiarate nel contesto globale sono slot dell'oggetto globale (window in JavaScript lato client).

Combinati, significano che gli oggetti nelle variabili globali durano per la durata del tuo script (a meno che la variabile non sia riassegnata). Questo è il motivo per cui dichiariamo le funzioni anonime: le variabili ottengono un nuovo oggetto di contesto che scompare non appena la funzione termina l'esecuzione. Oltre all'efficienza vince, riduce anche la possibilità di conflitti di nome.

Il tuo secondo esempio (con la funzione anonima interna) potrebbe essere un po 'troppo zelante, però. Non mi preoccuperei di "aiutare il garbage collector" - GC probabilmente non funzionerà comunque nel mezzo. Preoccupati per le cose che verranno mantenute costantemente intorno, non solo leggermente più lunghe di quanto non sarebbero altrimenti. Queste funzioni anonime autoeseguite sono fondamentalmente moduli di codice che naturalmente appartengono insieme, quindi una buona guida è di pensare se questo descrive quello che stai facendo.

Ci sono alcuni motivi per utilizzare le funzioni anonime all'interno delle funzioni anonime. Ad esempio, in questo caso:

(function() { 
    var bfa = new Array(24 * 1024*1024); 
    var calculation = calculationFor(bfa); 
    $('.resultShowButton').click(function() { 
    var text = "Result is " + eval(calculation); 
    alert(text); 
    }); 
})(); 

Ciò comporta che matrice gigantesca essere catturato dallo scatto richiamata in modo che non passa mai. È possibile evitare ciò mettendo in quarantena la matrice all'interno della propria funzione.

+0

Comprendo e concordo con l'utilizzo di questo come una misura per evitare di ingombrare lo spazio dei nomi globale. Penso che il mio esempio originale non abbia adeguatamente dimostrato la portata della mia domanda. Ho rivisto la mia domanda per includere un esempio migliore. –

+0

_Worry su cose che saranno mantenute costantemente intorno, non solo leggermente più lunghe di quanto sarebbe altrimenti._ Questo è esattamente quello che stavo cercando! Grazie per l'aiuto! –

1

Qualsiasi cosa aggiunta all'ambito globale rimarrà lì fino a quando la pagina non viene scaricata (a meno che non la rimuovi specificamente).

Generalmente è una buona idea mettere le variabili e le funzioni che appartengono insieme in un ambito locale o in un oggetto, in modo che aggiungano il meno possibile allo spazio dei nomi globale. In questo modo è molto più facile riutilizzare il codice, poiché è possibile combinare diversi script in una pagina con rischi minimi per la denominazione delle collisioni.

+0

Giusto. Sono d'accordo. La mia domanda è più se sia opportuno attaccare singoli blocchi di codice in funzioni anonime per minimizzare realmente il loro scopo. Un esempio potrebbe essere un oggetto che sto tenendo in giro, magari assegnandolo come membro di un nodo HTML, ma un singolo blocco al suo interno potrebbe semplicemente fare la cosa e poi essere cancellato. Credo che la mia domanda sia più specifica della garbage collection, e quanto dovrei lasciarlo per informare il mio stile. –

Problemi correlati