Циклическое добавление / удаление DOM-узлов вызывает утечки памяти в JavaScript? - PullRequest
6 голосов
/ 20 сентября 2010

Я пытаюсь отобразить динамически изменяемые данные, манипулируя элементами DOM (добавляя / удаляя их).Я обнаружил очень странное поведение почти всех браузеров: после удаления элемента DOM, а затем добавления нового, браузер не освобождает память, занятую удаленным элементом DOM.Посмотрите код ниже, чтобы понять, что я имею в виду.После того, как мы запустим эту страницу, она будет постепенно расходовать до 150 МБ памяти.Может кто-нибудь объяснить мне это странное поведение?Или может я что-то не так делаю?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
  <script type="text/javascript">
     function redrawThings() {
         // Removing all the children from the container
         var cont = document.getElementById("container");
         while ( cont.childNodes.length >= 1 ) {
            cont.removeChild(cont.firstChild);
         }

         // adding 1000 new children to the container
         for (var i = 0; i < 1000; i++) {
             var newDiv = document.createElement('div');
             newDiv.innerHTML = "Preved medved "  + i;
             cont.appendChild(newDiv);             
         }         
     }  
  </script>
  <style type="text/css">
    #container {
        border: 1px solid blue;
    }
  </style>
</head>
<body onload='setInterval("redrawThings()", 200);'>
  <div id="container"> </div>
</body>
</html>

Ответы [ 3 ]

1 голос
/ 20 сентября 2010

Я не могу воспроизвести это на FF 3.6.8 / Linux, но 200 мс для таймера довольно малы с такой большой повторной визуализацией DOM.На моей машине я замечаю, что при выполнении сценариев, интенсивно использующих JavaScript, помимо выполнения этого скрипта, таких как набор текста в этом поле ответа, использование памяти увеличивается, но высвобождается снова, когда я прекращаю вводить (в моем случае, около 16% памятииспользование).

Я полагаю, что в вашем случае сборщику мусора в браузере просто не хватает «свободного времени», чтобы фактически удалить эти узлы из памяти.

0 голосов
/ 20 сентября 2010

Не уверен, повлияет ли это на синхронизацию, и это, вероятно, действительно плохая практика, но вместо того, чтобы зацикливаться на дочерних узлах, не могли бы вы просто установить innerHTML для div в "" ??

0 голосов
/ 20 сентября 2010

Это потому, что удаление узла из дерева DOM не удаляет его из памяти, он все еще доступен, поэтому будет работать следующий код:

var removed = element.removeChild(element.firstChild);
document.body.appendChild(removed);

Этот код удалит первого потомка из element, а затем, после его удаления, добавит его в конец документа. Вы действительно ничего не можете сделать, кроме как сделать свой код более эффективным с меньшим количеством удалений.

Для получения дополнительной информации посетите страницу Node.removeChild в Центре разработчиков Mozilla.

...