2010-09-24 2 views
45

Мой код JavaSript создает список из LI элементов. Когда я обновляю список, использование памяти растет и никогда не опускается. Я тестировал в sIEve, и это показывает, что браузер сохраняет все элементы, которые должны были быть удалены с помощью команд jQuery $.remove() или $.empty.Как удалить элементы DOM без утечек памяти?

Что делать, чтобы удалить узлы DOM без утечки памяти?

См. my other question по конкретному коду.

ответ

8

Вы удалили слушателей любого мероприятия? Это can cause memory leaks.

+0

Я даже сделать для каждого элемента $ (это) .unbind() HTML ("") удалить(); – podeig

+2

Я думал, что jQuery автоматически удаляет обработчики событий, когда вы делаете element.remove(), no? – jayarjo

+0

@jayarjo - это – vsync

43

DOM сохраняет все узлы DOM, даже если они были удалены из самого дерева DOM, единственный способ удалить эти узлы - это обновить страницу (если вы поместите список в iframe, обновление не будет быть заметным)

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

Лучшая практика повторного использования узлов.

EDIT: Попробуйте это:

var garbageBin; 
window.onload = function() 
    { 
    if (typeof(garbageBin) === 'undefined') 
     { 
     //Here we are creating a 'garbage bin' object to temporarily 
     //store elements that are to be discarded 
     garbageBin = document.createElement('div'); 
     garbageBin.style.display = 'none'; //Make sure it is not displayed 
     document.body.appendChild(garbageBin); 
     } 
    function discardElement(element) 
     { 
     //The way this works is due to the phenomenon whereby child nodes 
     //of an object with it's innerHTML emptied are removed from memory 

     //Move the element to the garbage bin element 
     garbageBin.appendChild(element); 
     //Empty the garbage bin 
     garbageBin.innerHTML = ""; 
     } 
    } 

Чтобы использовать его в контексте, вы могли бы сделать это следующим образом:

discardElement(this); 
+9

Я не знал о «DOM сохраняет все узлы DOM, даже если они были удалены из самого дерева DOM». Вы имеете в виду функцию $ .remove() ничего не делать? – podeig

+0

Сколько MegaBite должно использоваться для запуска сборщика мусора. Я думаю, 150Mb должно быть достаточно. Но это не работает для меня. – podeig

+0

Отредактировано, попробуйте ввести код. –

2

ниже код не попадала на моем IE7 и других браузеров:

<html> 
<head></head> 
<body> 
    <a href="javascript:" onclick="addRemove(this)">add</a> 
    <ul></ul> 
    <script> 
     function addRemove(a) { 
      var ul = document.getElementsByTagName('UL')[0], 
       li, i = 20000; 
      if (a.innerHTML === 'add') { 
       while (i--) { 
        li = document.createElement('LI'); 
        ul.appendChild(li); 
        li.innerHTML = i; 
        li.onclick = function() { 
         alert(this.innerHTML); 
        }; 
       } 
       a.innerHTML = 'remove'; 
      } else { 
       while (ul.firstChild) { 
        ul.removeChild(ul.firstChild); 
       } 
       a.innerHTML = 'add'; 
      } 
     } 
    </script> 
    </body> 
</html> 

Возможно, вы можете попытаться выявить некоторые отличия с ваш код.
Я знаю, что IE течет гораздо меньше, когда вы вставляете сначала узел в DOM, прежде чем что-либо делать с ним, например: присоединять к нему события или заполнять его свойство innerHTML.

13

Это скорее FYI, чем реальный ответ, но это также довольно интересно.

От DOM-спецификации W3C (http://www.w3.org/TR/DOM-Level-2-Core/core.html):

В DOM API-интерфейсы Основные разработаны для совместимости с широким спектром языков, включая языки сценариев общего пользования и более сложные языки, используемые в основном профессиональными программистами. Таким образом, API-интерфейсы DOM должны работать с различными философиями управления памятью, от языковых привязок, которые вообще не предоставляют пользователю управление памятью через те (в частности, Java), которые предоставляют явные конструкторы, но автоматически предоставляют автоматический механизм сбора мусора вернуть неиспользуемую память тем (особенно C/C++), которые обычно требуют, чтобы программист явно выделял память объекта, отслеживал, где он используется, и явно освобождает его для повторного использования. Чтобы обеспечить согласованный API на этих платформах, DOM вообще не затрагивает проблемы управления памятью, но вместо этого оставляет их для реализации. Ни одно из явных языковых привязок, определенных DOM API (для ECMAScript и Java), не требует каких-либо методов управления памятью, но для привязки DOM для других языков (особенно C или C++) может потребоваться такая поддержка. Эти расширения будут нести ответственность за адаптацию DOM API к определенному языку, а не к рабочей группе DOM.

Другими словами: управление памятью осуществляется до реализации спецификации DOM на разных языках. Вам нужно будет изучить документацию по реализации DOM в javascript, чтобы узнать какой-либо метод удаления объекта DOM из памяти, который не является взломом. (Существует, однако, очень мало информации на сайте MDC по этой теме.)


В записке о jQuery#remove и jQuery#empty: от того, что я могу сказать, ни один из этих методов делает ничего, кроме удаления Object с от DOM node s или удалить DOM node s из document. Они только удаляют Это, конечно, не означает, что для этих объектов нет памяти (хотя они еще не находятся в document).

Edit: Приведенный выше отрывок был излишним, поскольку очевидно, Jquery не может делать чудеса и работы по реализации DOM используемого браузера.

+1

из jQuery .remove() API: «... В дополнение к самим элементам все связанные события и данные jQuery, связанные с элементами, удаляются. Чтобы удалить элементы без удаления данных и событий, используйте .detach().« – vsync

+0

Вы сказали, что« из того, что я могу сказать, ни один из этих методов не делает ничего, кроме удаления объектов из узлов DOM или удаления узлов DOM из документа ».. поэтому я привел из API, что он делает больше, чем это. все связанные события. – vsync

+1

Контекст был выделен памятью. Но, ну, я пропустил прохождение на 'jQuery'. – FK82

1

Если у вас есть на «после починки» утечка, и должны делать это без переписывания всего вашего кода, чтобы принять замыкания, циклические ссылки и т.д. в аккаунте, используйте Douglas Crockfords Purge-метод до удаления:

http://javascript.crockford.com/memory/leak.html

Или использовать эту затворных починки обходной путь:..

http://laurens.vd.oever.nl/weblog/items2005/closures/

+2

, пожалуйста, исправьте ссылку –

Смежные вопросы