Per essere completamente onesti, è necessario un rapido sguardo al codice di prova in cui è stato replicato, ma ho un'idea generale di ciò che si sta verificando. Se ho torto e puoi fornire un codice di prova che lo provi, ti prego di farmelo sapere.
Come sembra già sapere, per 'ripulire', Javascript non vuole più riferimenti all'elemento che vuole essere liberato.
Un semplice esempio:
// Currently not eligible for garbage
var myObj = {
data : 'test'
};
// Reference data inside myObj
// A unique identifier to myObj.data now exists
var myData = myObj.data;
// Whoops
myObj = 'something else';
// Because myData exists, so does data and can not be freed either, understandable
// This sounds simple and logical but most do not understand what is happening in the engine
// A relationship has been born between 'myData' and 'data' and as long as it exists, it is not eligible for garbage and remains in memory
console.log(myData);
Il codice è probabilmente più complicato di questo, ma questo potrebbe aiutare a spiegare come, da qualche parte, l'immondizia non può essere raccolto come la catena di portata può essere seguito a un riferimento.
consideri il seguente
function oops(text){
function doStuff(){
return text.toLowerCase();
}
return doStuff();
}
// 'doStuff' stays alive thanks to 'test' below.
var test = oops('closure');
la funzione doStuff
non saranno spazzatura collezionati perché viene fatto riferimento da test
.
// You can see where this is headed. We have 2 references to the same 'doStuff' function object with separate unique identifiers now below.
var test2 = oops('closures...');
// This is now another unique identifier to 'doStuff'
var test3 = test2;
// doStuff survives yet still
test = 0;
test2 = 0;
// Now we let the function object of 'doStuff' be freed because there is no longer any references to it
test3 = 0;
Questa è essenzialmente una perdita di memoria che abbiamo creato. Ogni volta che si chiama oops
si sta creando un oggetto funzione doStuff
con un identificativo univoco.
un modo per evitare che questo potrebbe essere
function doStuff(text){
return text.toLowerCase();
}
function oops(text){
return doStuff();
}
var test = oops('closure');
ora non abbiamo perdite di memoria. doStuff
è invocato e non creato.
Uno sguardo più da vicino al codice e troverete che probabilmente lo state facendo da qualche parte.
Se hai problemi con gli elementi e penso che potresti essere, IBM has a good article about circular references potresti voler dare un'occhiata.
E 'tardi e alcuni di questo è stato testato, ma la teoria è ancora lì, quindi se ho scritto male qualcosa, ecc, fatemelo sapere e vi posso dare un'occhiata domani per i futuri visitatori di questa pagina.
Questi metodi sono persino in grado di essere raccolti? Stai creando chiusure? Potresti inavvertitamente creare una perdita di memoria? – Jesse
La [Guida di stile JavaScript di Google] (https://google.github.io/styleguide/javascriptguide.xml?showone=Closures#Closures) ha un esempio di chiusura che crea un riferimento circolare che genera una perdita di memoria. Se questo è il caso dell'OP, non è una novità: [1] (http://stackoverflow.com/questions/19550253), [2] (http://stackoverflow.com/questions/16442201), [3 ] (http://stackoverflow.com/questions/11186750). Non so perché, ma i moderni motori JS non sembrano avere una soluzione per affrontare questa fonte molto comune di perdite di memoria. –
@ GOTO0 Sono consapevole che una chiusura mantiene i riferimenti alle variabili che utilizza (come potrebbe funzionare diversamente?) Ma che mantiene anche variabili di inclusione non utilizzate è nuova per me, e in realtà piuttosto deludente. Tuttavia, quella guida di stile dice "un riferimento circolare e quindi una perdita di memoria". Non è un'affermazione obsoleta che si applica solo al conteggio dei riferimenti GC? Pensavo che mark-and-sweep avrebbe dovuto rendere questo un non-problema? E se quella parte è sbagliata, il resto di questa guida è affidabile? –