2011-11-13 12 views
8

Ho studiato un po 'su questo, ma soprattutto mettendo insieme altre domande, il che lascia ancora qualche dubbio. In un'app che non aggiorna la pagina del browser in qualsiasi momento e potrebbe durare per un po '(ore) senza chiudere (supponendo che il refresh di una pagina o la navigazione verso un'altra riavvii il codice js), qual è il modo migliore per garantire che gli oggetti siano rilasciato e che non c'è perdita di memoria.Vita degli oggetti JavaScript e perdite di memoria

Questi sono gli scenari specifici Sono preoccupato:

Tutto il codice qui sotto è all'interno di un modello del modulo rivelatore.

mycode = function(){}() 

variabili all'interno delle funzioni, sono sicuro che questo è raccolto dal GC bene

function(){ var h = "ss";} 

variabili all'interno del modulo, dovrebbe g = null quando non è più necessaria?

var g; 
function(){ g = "dd";} 

E infine la vita di un jqXHR: viene ripulito dopo il suo ritorno? Dovrebbe essere impostato su null in tutti i casi come precauzione se conservato all'interno di una funzione o di un modulo?

Se facendo questo, è vero X ripulito dal GC dopo ritorna ?:

function(){ 
    var x = $.get(); 
    x.done = ...; 
    x.fail = ...; 
} 

Che ne dite di quando si fa questo, sarà anche essere ripulito dopo x rendimenti ?:

var x; 
function(){ 
    x = $.get(); 
    x.done = ...; 
    x.fail = ...; 
} 

Infine, c'è un modo per pulire tutte le variabili e riavviare un modulo senza riavviare il browser?

+0

Se stai pensando a perdite di memoria, non dovresti pensare alle variabili. Pensa agli oggetti e ai riferimenti e alle implicazioni di raggiungibilità che questi ultimi hanno per il primo. – delnan

+0

Sì, è solo che penso a tutto in js come variabile, ma capisco il tuo punto. Grazie. –

risposta

7

variabili all'interno delle funzioni, sono sicuro che questo è raccolto dal GC bene

Sì.

variabili all'interno del modulo, dovrebbe g = null quando non è più necessario?

Sicuro.

E infine la durata di un jqXHR: viene ripulito dopo il suo ritorno? Dovrebbe essere impostato su null in tutti i casi come precauzione se conservato all'interno di una funzione o di un modulo?

vari browser hanno dovuto bug relativi alla XHR che ha causato il onreadystatechange e tutto si chiuse sopra di rimanere inesigibili a meno che il dev è stato attento a sostituirlo con un valore fittizio (xhr.onreadystatechange = new Function('')) ma credo che jQuery gestisce questo per voi.

Infine, c'è un modo per pulire tutte le variabili e riavviare un modulo senza riavviare il browser?

Lo stato globale associato alla pagina occuperà la memoria del browser fino a quando la pagina non verrà espulsa dalla cronologia del browser. location.replace può aiutarti qui lasciandoti uccidere la pagina corrente e sostituirla con una nuova versione della stessa app senza espandere lo stack cronologico.

Sostituire il documento corrente con quello nell'URL fornito. La differenza rispetto al metodo assign() è che dopo aver utilizzato replace() la pagina corrente non verrà salvata nella cronologia delle sessioni, il che significa che l'utente non sarà in grado di utilizzare il pulsante Indietro per spostarsi ad esso.

Quando si utilizza la parola "modulo", che non è un termine che ha un significato ben definito per il browser o il suo interprete JavaScript quindi non c'è modo di sfrattare un modulo e solo un modulo dalla memoria. Ci sono diverse cose che si devono preoccupare di che potrebbe mantenere le cose in memoria:

  1. I riferimenti a oggetti JavaScript che sono stati allegati ai nodi DOM e tutto ciò che chiudono sopra - i gestori di eventi sono un esempio molto comune.
  2. Live setInterval e setTimeout richiamate e tutto ciò che chiudono.
  3. Proprietà dell'oggetto globale e tutto ciò che chiudono.
  4. Come hai notato, le proprietà di alcuni oggetti host come le istanze XHR, i callback web worker, ecc. E (hai indovinato) tutto ciò che chiudono.

Qualsiasi schema che sta per scaricare un modulo e solo un modulo dovrebbe occuparsi di tutti questi e capire quali di essi fanno parte del modulo e quali no. Questo è un sacco di diversi tipi di pulizia.

+0

'delete' funziona solo per proprietà, non per' g' qui. http://jsfiddle.net/hM5ke/ – pimvdb

+0

@pimvdb, grazie. Modificato. –

+0

IYO, suggeriresti ** ** che una variabile jqXHR sia impostata su null quando non è più necessaria? Ho appena impostato un jqXHR; ottenuto la mia risposta, caricato nuovo html nel div in cui si trovava e posso ancora accedere alla variabile. Mentre apprezzo che il GC farà la cosa (alla fine), sarebbe meglio annullarlo? o lasciare che il js gc faccia la sua cosa? –

1

Javascript è un linguaggio spazzatura. Si affida al garbage collector per ripulire la memoria inutilizzata. Quindi, in sostanza, devi avere fiducia che il GC farà il suo lavoro.

Il GC (eventualmente, non immediatamente) raccoglierà oggetti che non sono raggiungibili. Se hai un riferimento a un oggetto, allora è potenzialmente ancora in uso, e quindi il GC non lo toccherà.

Se non si ha alcun riferimento all'oggetto, direttamente o indirettamente, il GC sa che l'oggetto non può essere utilizzato e l'oggetto può essere raccolto. Quindi tutto ciò che devi fare, in realtà, è assicurarti di reimpostare qualsiasi riferimento all'oggetto.

Tuttavia, il GC non fornisce alcuna garanzia su quando l'oggetto verrà raccolto. E non dovresti aver bisogno di preoccupartene.

1

In realtà le uniche falle che dovresti preoccuparti sono le chiusure.

function foo(a){ 
    var b = 10 + a; 
    return function(c){ 
     return b + c; 
    } 
} 

var bar = foo(20); 
var baz = bar(5); 

Il GC non ha alcun modo per eliminare var b - è fuori portata. Questo è un grosso problema con IE, non tanto con Mozilla e tanto meno con Chrome.

+0

Ovviamente, non è una perdita permanente. Una volta che la funzione di ritorno ottiene il GC, allora anche 'b' otterrà GC'd. – Raynos

+0

Se non sbaglio, 'b' ottiene GC'd quando non ci sono riferimenti alla funzione restituita dal momento che quello è l'unico posto in cui è presente un riferimento a b dopo il ritorno di' foo'. –

+0

http://msdn.microsoft.com/en-us/library/bb250448(v=vs.85).aspx – AlienWebguy

0

Il primo esempio con 'g', g deve essere impostato su null. Manterrà il puntatore a "dd" altrimenti.

Nel secondo esempio, la 'x' nel primo caso non ha bisogno di essere impostata su null, poiché quella variabile "andrà via" quando la funzione circostante si chiude. Nel secondo caso, con 'x' al di fuori della funzione, 'x' manterrà qualunque cosa gli sia stata assegnata, e che non sarà GC'd finché 'x' non sarà impostato su null o qualcos'altro.

+1

'" dd "' è una stringa primitiva e solo quel valore stesso; non un "puntatore" a qualcosa in JavaScript. – pimvdb

+0

@pimvdb, a seconda di come l'interprete raggruppa i valori letterali delle stringhe che si verificano all'interno dei corpi delle funzioni, il browser potrebbe essere in grado di eliminare la memoria utilizzata per memorizzare '" dd "' dopo la funzione 'function() {g =" dd " ; } 'viene raccolto. –

1

Tutte le variabili a cui non è più possibile accedere possono essere raccolte dal GC. Se dichiari una variabile all'interno di una funzione, una volta che la funzione viene chiusa, la variabile può essere rimossa. Lo è, quando il computer esaurisce la memoria o in qualsiasi altro momento.

Questo diventa più complicato quando si eseguono funzioni asincrone come XHR. Il fatto e fail le chiusure possono accedere a tutte le variabili dichiarate nelle funzioni esterne. Pertanto, finché è terminato con e fail, tutte le variabili devono rimanere in memoria. Una volta che la richiesta è finita, le variabili possono essere rilasciate.

In ogni caso, è necessario assicurarsi che ogni variabile sia dichiarata quanto più profonda possibile.

+0

Non è garantito che tale variabile * sia * rimossa una volta che la funzione è stata chiusa. Solo * può * essere rimosso da quel punto. – pimvdb

+0

Ok, ho corretto questo. L'interrogante ha chiesto delle perdite di memoria e quelle appaiono se non è possibile raccogliere le variabili. – Yogu

+0

@pimvdb, sono d'accordo su 'is' vs' can', ma i frame di attivazione sono oggetti e né loro né le proprietà chiuse che contengono sono collezionabili se fanno parte dell'ambito di qualsiasi chiusura live. Le modifiche alla semantica 'eval' in ES5 consentono alle chiusure di fare riferimento a un sottoinsieme di un frame di attivazione - alcune proprietà e non altre - ma i valori delle variabili locali non sono sempre selezionabili solo perché il frame di attivazione in cui appaiono è stato chiuso. –

1

Come regola generale con qualsiasi linguaggio raccolto con garbage (questo vale per Java, .NET e JavaScript per esempio), ciò che si vuole fare è assicurarsi che non ci sia un riferimento persistente a un blocco di memoria che vuoi che il GC ripulisca per te. Quando il GC guarda un blocco di memoria e scopre che c'è ancora qualcosa nel programma che fa riferimento a esso, allora eviterà di rilasciarlo.

Riguardo al jqXHR, non ha senso impostarlo su null alla fine di una chiamata di funzione AJAX. Tutti i parametri di un successo/errore/completamento AJAX saranno rilasciati una volta che la funzione ritorna dal GC a meno che jQuery non stia facendo qualcosa di bizzarro come mantenere un riferimento ad essi.

Problemi correlati