Жизнь объектов JavaScript и утечки памяти - PullRequest
9 голосов
/ 14 ноября 2011

Я немного исследовал эту тему, но в основном собрал воедино другие вопросы, что все еще оставляет некоторые сомнения.В приложении, которое не обновляет страницу браузера в любое время и может жить некоторое время (часы) без закрытия (при условии, что обновление страницы или переход на другую страницу перезапустят код js), каков наилучший способ убедиться, что объектывыпущен и утечки памяти нет.

Это особые сценарии, которые меня беспокоят:

Весь приведенный ниже код находится в разоблачающем шаблоне модуля.

mycode = function(){}()

переменных внутри функций, я уверен, что эта переменная собрана GC просто отлично

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

переменных внутри модуля, должен ли g = null, когда он больше не нужен?

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

И, наконец, жизнь jqXHR: очищается ли он после возвращения?Должно ли оно быть установлено на ноль во всех случаях в качестве меры предосторожности, если оно хранится внутри функции или модуля?

Если это сделать, очищается ли оно ХУ после его возврата?:

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

Как насчет этого, будет ли он очищаться и после возврата x?:

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

Наконец, есть ли способ очистить все переменные и перезапустить модуль без перезапуска браузера?

Ответы [ 6 ]

7 голосов
/ 14 ноября 2011

переменные внутри функций, я уверен, что эта сборка собрана GC просто отлично

Да.

переменные внутри модуля, должен ли g = null, когда он больше не нужен?

Конечно.

И, наконец, жизнь jqXHR: очищается ли он после возвращения? Должно ли оно быть установлено равным нулю во всех случаях в качестве меры предосторожности, если оно хранится внутри функции или модуля?

В различных браузерах были ошибки, связанные с XHR, из-за которых onreadystatechange и все, что он закрывал, оставалось невосприимчивым, если разработчик не был осторожен, чтобы заменить его фиктивным значением (xhr.onreadystatechange = new Function('')), но я считаю, что jQuery справится с этим для вас ,

Наконец, есть ли способ очистить все переменные и перезапустить модуль без перезапуска браузера?

Глобальное состояние, связанное со страницей, будет занимать память браузера до тех пор, пока страница не будет удалена из стека истории браузера. location.replace может помочь вам в этом, позволив вам убить текущую страницу и заменить ее новой версией того же приложения без расширения стека истории.

Заменить текущий документ документом по указанному URL. Отличие от метода assign() состоит в том, что после использования replace() текущая страница не будет сохранена в истории сеанса, а это означает, что пользователь не сможет использовать кнопку Назад для перехода к ней.

Когда вы используете слово «модуль», это не тот термин, который имеет четко определенное значение для браузера или его интерпретатора JavaScript, поэтому нет способа удалить модуль и только модуль из памяти. Есть несколько вещей, о которых вам нужно беспокоиться, которые могут сохранить вещи в памяти:

  1. Ссылки на объекты JavaScript, которые были присоединены к узлам DOM, и все, что они закрывают - обработчики событий - очень распространенный пример.
  2. Живые setInterval и setTimeout обратные вызовы и все, что они закрывают.
  3. Свойства глобального объекта и всего, что они закрывают.
  4. Как вы заметили, свойства определенных хост-объектов, таких как экземпляры XHR, обратные вызовы веб-работников и т. Д., И (как вы уже догадались) всего, что они закрывают.

Любая схема, которая собирается выгрузить модуль и только модуль, должна была бы иметь дело со всеми из них и выяснить, какие из них являются частью модуля, а какие нет. Это много разных видов очистки.

1 голос
/ 14 ноября 2011

Как правило, с любым языком для сбора мусора (это относится, например, к Java, .NET и JavaScript), вам нужно убедиться, что нет ссылки на нужный вам блок памяти. чтобы очистить ГК для вас. Когда GC смотрит на блок памяти и обнаруживает, что в программе все еще есть что-то, ссылающееся на него, он не будет освобождать его.

Что касается jqXHR, то нет смысла устанавливать их в null в конце вызова функции AJAX. Все параметры AJAX success / error / complete будут освобождены после того, как функция вернет GC, если jQuery не делает что-то странное, например, сохранение ссылки на них.

1 голос
/ 14 ноября 2011

Каждая переменная, к которой вы больше не можете получить доступ, может быть собрана GC. Если вы объявляете переменную внутри функции, после завершения функции переменная может быть удалена. - , когда на компьютере не хватает памяти или в любое другое время.

Это становится более сложным, когда вы выполняете асинхронные функции, такие как XHR. Закрытия done и fail могут обращаться ко всем переменным, объявленным во внешних функциях. Таким образом, до тех пор, пока могут выполняться done и fail , все переменные должны оставаться в памяти. После завершения запроса переменные могут быть освобождены.

В любом случае, вы должны просто убедиться, что каждая переменная объявлена ​​настолько глубоко, насколько это возможно.

1 голос
/ 14 ноября 2011

На самом деле единственные утечки, о которых вам следует беспокоиться, это замыкания.

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

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

GC не имеет возможности удалить var b - это выходит за рамки. Это большая проблема с IE, не столько с Mozilla, сколько с Chrome.

1 голос
/ 14 ноября 2011

Javascript - это язык для сбора мусора.Он использует сборщик мусора для очистки неиспользуемой памяти.По сути, вы должны верить, что GC выполнит свою работу.

GC (в конце концов, не обязательно сразу) будет собирать объекты, которые вам недоступны.Если у вас есть ссылка на объект, он потенциально все еще используется, и поэтому GC не будет к нему прикасаться.

Если у вас нет ссылки на объект, прямо или косвенно, то GC знаетчто объект не может быть использован, и объект может быть собран.Так что все, что вам нужно сделать, это убедиться, что вы сбросили все ссылки на объект.

Однако GC не дает никаких гарантий относительно , когда объект будет собран.И вам не нужно беспокоиться об этом.

0 голосов
/ 14 ноября 2011

Это первый пример с 'g', для g должно быть установлено значение null. В противном случае он сохранит указатель на «dd».

Во втором примере 'x' в первом случае не нужно устанавливать в null, так как эта переменная "исчезнет", когда выйдет окружающая функция. Во втором случае, когда «x» находится вне функции, «x» сохранит все, что ему присвоено, и это не будет GC'd до тех пор, пока «x» не будет установлено в ноль или что-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...