Javascript + Knockout.js memory leak - How to make sure object is being destroyed?

安稳与你 提交于 2019-12-25 02:51:57

问题


I am using google's 3 Snapshot method to find memory leaks on the page. Page is running on Knockout.js and Jquery Mobile UI. I have already narrowed down to one of memory leaking divs. Between each snapshot I am running this script to clear the memory leaking object.

$('.paddedContentContainer').children().each(function(index,item){
console.log(item); 
$(item).off(); 
ko.cleanNode($(item)); 
$(item).remove();
item = null;
});

.paddedContentContainer is parent of leaking object.
Now the interesting part is that I can still see object in retained object tree. In screenshot below you can see I am filtering on objects in Snapshot 3 that are retained from Snapshots 1 and 2, and by text it's visible that $0 from console in same object that is on the screen (Event Sales Order & ....).

I am assuming that .off(); and .remove(); isin't enough for object to be collected.
How to destroy all references to this object for good?


回答1:


Have you looked at this post: How to destroy a DOM element with jQuery??

Luke's response seems interesting:

If you want to completely destroy the target, you have a couple of options. First you can remove the object from the DOM as described above...

console.log($target); // jQuery object $target.remove(); // remove target from the DOM console.log($target); // $target still exists Option 1 - Then replace target with an empty jQuery object (jQuery 1.4+)

$target = $(); console.log($target); // empty jQuery object Option 2 - Or delete the property entirely (will cause an error if you reference it elsewhere)

delete $target; console.log($target); // error: $target is not defined

Maybe you should to delete $(item) in the end.




回答2:


.remove() just removes the element from the DOM, if anything is still referencing it (in your code) it will not be Garbage Collected.

Edit

Yes the .remove() is the correct way of detaching/removing it from the DOM, but it is still held in memory because other things are referencing it (knockout's internals in this example).

One way, and the way I do it, is to keep a collection of all the high-level DOM elements that I create in my controls, then have a destroy function that loops these and calls .remove() on them and assigns them to null

E.g (Note this is held within each control object (no leaky global stuff):

var elements = 
{
    'table' : $('#some_table'),
    'button' : $('#some_button')
};


function destroy()
{
    for(var key in elements)
    {
        elements[key].remove();
        elements[key] = null;
    }
}

You may be able to take this approach with knockout.




回答3:


Adding an answer for those who will be satisfied with knockout.js reference removal only. This removed <div> at hand from object tree.

 $('.paddedContentContainer').children().each(function(index,item){
     $(item).off(); 
     ko.removeNode(item);
     $(item).remove();
     item = null;
 });


来源:https://stackoverflow.com/questions/23409499/javascript-knockout-js-memory-leak-how-to-make-sure-object-is-being-destroye

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!