Чтобы быть полностью честным, нам нужно быстро взглянуть на код, где вы воспроизвели это, но у меня есть общее представление о том, что вы испытываете. Если я ошибаюсь, и вы можете предоставить некоторый тестовый код, подтверждающий это, пожалуйста, дайте мне знать.
Как вы, кажется, уже знаете, чтобы «очистить», Javascript не хочет больше ссылок на элемент, который хочет быть освобожденным.
Простой пример:
// 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);
Ваш код, вероятно, более сложным, чем это, но это могло бы помочь объяснить, как, где, мусор не может быть собрана как цепочка областей видимости может следовать до ссылки.
Рассмотрим следующий
function oops(text){
function doStuff(){
return text.toLowerCase();
}
return doStuff();
}
// 'doStuff' stays alive thanks to 'test' below.
var test = oops('closure');
doStuff
функция не будет собран сборщиком мусора, так как он ссылается 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;
Это по существу утечка памяти, которую мы создали. Каждый раз, когда вы вызываете oops
, вы создаете объект функции doStuff
с уникальным идентификатором.
Способ избежать этого может быть
function doStuff(text){
return text.toLowerCase();
}
function oops(text){
return doStuff();
}
var test = oops('closure');
Теперь у нас нет никаких утечек памяти. doStuff
был был использован и не создано.
Более пристальный взгляд на ваш код, и вы обнаружите, что вы, вероятно, это делаете.
Если вы возитесь с элементами, и я думаю, что вы можете быть, IBM has a good article about circular references, вы можете взглянуть на них.
Это поздно, и некоторое это проверялось, но теория до сих пор существует, так что если я неправильно что-то и т.д., дай мне знать, и я могу посмотреть завтра для будущих посетителей этой страницы.
Являются ли эти методы даже способными собирать мусор? Вы создаете закрытие? Не могли бы вы случайно создать утечку памяти? – Jesse
В [Руководстве по стилю JavaScript JavaScript] (https://google.github.io/styleguide/javascriptguide.xml?showone=Closures#Closures) приведен пример закрытия, который создает циклическую ссылку, приводящую к утечке памяти. Если это относится к OP, то это ничего нового: [1] (http://stackoverflow.com/questions/19550253), [2] (http://stackoverflow.com/questions/16442201), [3 ] (http://stackoverflow.com/questions/11186750). Не знаю, почему, но современные двигатели JS, похоже, не имеют решения для решения этого очень распространенного источника утечек памяти. –
@ GOTO0 Я знаю, что замыкание содержит ссылки на охватывающие переменные, которые он использует (как он мог функционировать иначе?), Но что он также сохраняет неиспользуемые закрывающие переменные, для меня новичок, и на самом деле довольно разочаровывает. Однако в этом руководстве по стилю говорится «круговая ссылка и, следовательно, утечка памяти». Разве это не устаревшее утверждение, которое применяется только к счетчику GC? Я думал, что марка-и-sweep должна была сделать это без проблем? И если эта часть неверна, остальная часть этого руководства заслуживает доверия? –