Как уничтожить объект JavaScript?

81

Недавно я наткнулся на одно из своих приложений, которое потребляет слишком много памяти и увеличивается на 10 МБ / с.

Итак, мне нравится знать, как лучше всего уничтожить объект и переменные JavaScript, чтобы потребление памяти оставалось низким, а мой FF не мог быть уничтожен.

Я вызываю два своих кода JavaScript каждые 8 ​​секунд без перезагрузки страницы.

function refresh() {
    $('#table_info').remove();
    $('#table').hide();
    if (refreshTimer) {
        clearTimeout(refreshTimer);
        refreshTimer = null ;
    }
    document.getElementById('refresh_topology').disabled=true; 
    $('<div id="preload_xml"></div>').html('<img src="pic/dataload.gif" alt="loading data" /><h3>Loading Data...</h3>').prependTo($("#td_123"));
    $("#topo").hide();
    $('#root').remove();
    show_topology();
}

Как я могу увидеть, какая переменная вызывает накладные расходы памяти и метод остановки выполнения этого процесса?

Амит Шах
источник
1
Рассматривали ли вы изолирование частей вашего кода с помощью замыканий?
Ю.С.
1
Вы что-нибудь пробовали? Нравится использовать obj = null?
Флориан Маргейн,
А) Что делает show_topology? --- Б) Вы когда-нибудь убираете то, что добавляете #td_123? --- В) Есть ли где-нибудь живая версия этого?
Deestan

Ответы:

93

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

var namespace = {};

namespace.someClassObj = {};

delete namespace.someClassObj;

Использование deleteключевого слова приведет к удалению ссылки на свойство, но на нижнем уровне сборщик мусора (GC) JavaScript получит больше информации о том, какие объекты нужно удалить.

Вы также можете использовать Инструменты разработчика Chrome, чтобы получить профиль памяти вашего приложения и узнать, какие объекты в вашем приложении нужно уменьшить.

Ёхай Акока
источник
12
Нажмите F12, чтобы получить инструменты разработчика. Перейдите на вкладку «Профиль» и нажмите «Пуск», чтобы запустить профиль. Вы можете выполнить профилирование на JS CPU, CSS Selector и сделать снимок кучи.
Сарат
3
или в последней версии Chrome введите слово «производительность» в консоли js
Дэвид Морроу
Возможно, это очевидно, но вы можете назвать свое пространство имен чем-то вроде "g" и сэкономить много времени на вводе текста. Используйте g.curItem = ... вместо var curItem = ... и сохраните ввод, а также разрешите g = undefined очистить все распределение глобальной памяти.
Дэвид Спектор
31

Вы не можете удалять объекты, они удаляются, когда на них больше нет ссылок. Вы можете удалять ссылки с помощью delete.

Однако, если вы создали круговые ссылки в своих объектах, возможно, вам придется отделить некоторые вещи.

CodeClown42
источник
2
Не могли бы вы добавить пример круговой ссылки, которая не будет перехвачена сборщиком мусора? Спрашиваю друга! ;)
emilhem
@emilhem, вы можете сослаться на сборщик мусора, и он удалит себя и Интернет - взрыв, возможно, создаст черную дыру в ЦЕРНе. Вы думали об этом примере?
Эль Мак,
28

Хотя существующие ответы дали решения для решения проблемы и второй половины вопроса, они не дают ответа на аспект самопознания первой половины вопроса, выделенного жирным шрифтом:

«Как я могу увидеть, какая переменная вызывает накладные расходы памяти ...?»

Возможно, 3 года назад он был не таким надежным, но раздел « Профили » инструментов разработчика Chrome теперь стал довольно мощным и многофункциональным. У команды Chrome есть полезная статья об его использовании и, следовательно, о том, как сборка мусора (GC) в javascript, что является ядром этого вопроса.

Поскольку deleteэто в основном корень принятого в настоящее время ответа Йохая Акока, важно помнить, что делает удаление. Это не имеет значения, если не сочетается с концепциями работы GC в следующих двух ответах: если существует ссылка на объект, он не очищается. Ответы более правильные, но, вероятно, не так ценится, потому что они требуют большего размышления, чем просто написание «удалить». Да, одним из возможных решений может быть использование delete, но не имеет значения, есть ли еще одна ссылка на утечку памяти.

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

Поскольку deleteздесь было упомянуто, также может быть полезно предоставить ресурс Understanding Delete . Хотя это не попасть в любой из фактического решения , которое действительно связано с сборщика мусора в JavaScript.

Швайдогг
источник
9

Структурируйте свой код так, чтобы все ваши временные объекты располагались внутри замыканий, а не в глобальном пространстве имен / глобальных свойствах объекта, и выходили за пределы области видимости, когда вы закончили с ними. Об остальном позаботится GC.

Олег В. Волков
источник
1

Я столкнулся с такой проблемой, и у меня возникла идея просто изменить innerHTML дочерних элементов проблемного объекта.

adiv.innerHTML = "<div...> the original html that js uses </div>";

Кажется грязным, но это спасло мне жизнь, так как работает!

Серхио Абреу
источник