[Javascript]: Создаются ли элементы с использованием метода CreateElement, вызывают утечку памяти, если они не удалены должным образом?
Я создаю элементы, используя метод createElement, и добавляю их к некоторому родительскому элементу. Позже я очистил innerHTML родительского элемента. Это приведет к утечке памяти? что происходит с созданным элементом? Если это утечка памяти, как ее обрабатывать?. также, если есть какая-либо функция обратного вызова, связанная с элементом, нужно ли ее отсоединять?
var spanelem = document.createElement('span');
spanelem.onclick = function(){
CallMe();
};
var parentdiv = document.getElementById('ParentCnt');
parentdiv.appendChild(spanelem);
.....
.....
parentdiv.innerHTML = " "; //is this memory Leak ? what happens to spanelem?
Ответы
Ответ 1
Это зависит.
Если у вас есть код, который вы даете - spanElem все еще существует в памяти (если var spanelem
был в глобальной области действия, и вы не выполнили spanelem = null
), вы получите доступную ссылку на объект.
В противном случае, если spanElem имеет единственную ссылку из обработчика onClick - это будет утечка памяти только в IE8-. Все современные браузеры обрабатывают такие случаи и очищают память от сбора мусора.
Я предполагаю, что вы имеете в виду не тот же код, но просто принцип - в таком случае вы можете проверить, нет ли других обработчиков, которые имеют ссылку на spanElem в их лексическом env, если это так - вы можете просто очистить ссылку при добавлении
spanelem = null;
после
parentdiv.appendChild(spanelem);
Проверьте более подробную информацию в MDN
P.S.
если вы запустите следующий код
var spanelem = document.createElement('span');
spanelem.onclick = function(){
CallMe();
};
var parentdiv = document.getElementById('ParentCnt');
parentdiv.appendChild(spanelem);
parentdiv.innerHTML = '';
console.log(spanelem);
вы обнаружите, что spanelem все еще существует (он будет таким же, если вы запустите
setTimeout(function(){ console.log(spanelem); }, 9999); // some huge delay here
) - но единственная причина в том, что для кода ниже мы сохраняем ссылку для объекта spanelem, поэтому gc не удаляет объект. Если мы его не будем использовать, - gc удалит на нем объект
Ответ 2
В целом, если есть озабоченность в отношении сбора мусора, то для смягчения этой проблемы требуется создание закрытия для сборщика мусора для целей.
Как только все ссылки удаляются в переменную из среды переменных и лексической среды, переменная имеет право на сбор.
Это означает, что инкапсуляция переменной в свой собственный контекст выполнения обеспечит минимальное воздействие на эти среды. Это можно сделать с помощью выраженного функционального выражения (IIFE).
(function(){
var spanelem = document.createElement('span');
spanelem.onclick = function(){
CallMe();
};
var parentdiv = document.getElementById('ParentCnt');
parentdiv.appendChild(spanelem);
})()
//CONT'D
... cont'd: На этом этапе единственная ссылка остается через DOM. Использование appendChild вызывает оплату документа, и поэтому, если что-то еще, что вызывает оплату, например,.innerHTML, эта запись может быть удалена. Позже использование parentdiv.innerHTML = " "
приведет к тому, что запись будет удалена, и сборщик мусора в конечном итоге, в своем собственном темпе, сможет удалить выделение памяти, если это необходимо.