I am wondering whether it is necessary to manually delete an element that has been detached with jQuery's detach() function (and all references to it has been null'ed).
Here is the JavaScript that I have tried.
For example:
elem = $(".test").detach();
elem = null;
Is the element completely gone, like with $(".test").remove(); or is something like elem.remove() needed?
Edit: Including my comment to the question:
I am detaching multiple elements. Some of them get reused (reinjected in DOM), but others need to be removed permanently after detaching.
Is it necessary to manually delete an element that has been detached with jQuery's detach() function (and all references to it has been null'ed).
You cannot "delete" an element. Garbage collector will automatically collect it when there are no references left. If you have detached it, it will be wiped from the memory without problems.
However, this is not the difference between detach and remove. When simply detaching it, some data that jQuery stored not on the element but in its internal cache will be leaked. You would need to explicitly call the [internal!] cleanData method on the elements to fix that - but you should simply call .remove().
You shouldn't have to worry about that. If there isn't a reference around to the element that has been detached, the Garbage Collector will clean it up.
Although, you're probably better off calling remove(). detach() is meant specifically for elements that you want to keep around (it maintains all the jQuery specific data associated with the element). Both end up calling elem.parent.removeChild on the actual DOM element. As far as I know there isn't a way to manually delete or destroy it, but that's the job of the Garbage Collector anyways.
Straight from jQuery documentation:
The .detach() method is the same as .remove(), except that .detach()
keeps all jQuery data associated with the removed elements. This
method is useful when removed elements are to be reinserted into the
DOM at a later time.
and .remove()
method takes elements out of the DOM.
So you should be covered.
Related
Right now if you want to reuse a certain dom element, you clone it and then append it. If you just append it then it's removed from its previous position, i.e. only one of it can exist. Therefore, you clone it first. Which is great in scnearios where that's needed behavior but not in all situations, for example. If it has an iframe, cloning it would cause to refetch the iframe each time.
But if you could refer, pass by reference, to existing DOM node then you'd only have one copy of a dom and wont need to clone.
I would like to know if detaching a div on load and appending that same div on a click will increase memory? When you detach a div (filled with images) is the div and image information kept in memory?
For example:
<div class="divContain-one">
<img src="test.png">
</div>
<div class="divContain-two"></div>
var divContainingImage = $("#divContain-one").detach();
$("button").click(function(){
$("#divContain-two").append(divContainingImage);
});
It shouldn't increase memory usage significantly. The variable simply contains a reference to same memory that held the DOM element, and any related jQuery data, before it was detached. All that has happened is that the DOM itself no longer has a reference to that memory.
When you append it, you don't increase the memory, either. It simply adds a reference to the same object to the new location in the DOM, it doesn't make a copy.
The information has to be kept in memory -- how else could it know what to add to the DOM when you append?
One caveat: the act of calling $("#divContainingImage") creates a jQuery object that wraps around the DOM element, and the variable contains a reference to this object, not just the DOM element. This does increase memory usage, independent of what .detach() does.
According to jquery documentaion detach method keeps all data associated with the removed element.
So, yes, especially taking the fact that you declared a variable and assigned returned data from detach method to it - data is definitely stored in memory. Anyway, keep in mind, that such memory usage is not significant if we are not talking about hundreds or thousands of elements.
You also need to consider if there are event listeners attached to the DOM object.
If you remove an object from the page then the memory can eventually be cleaned once there are no more references to it.
If you remove a and the has a click listener then that can continue to sit in memory indefinitely. Remove the listeners first then remove the DOM object. That way the DOM object can be removed from memory eventually.
I am registering a click listener on a DOM element via jQuery.on(). If later on that element is removed from the DOM -- maybe indirectly, e.g. by by replacing some parent's content via $(parent).html(...), should I still bother to remove my handler via jQuery.off()?
Even if the element will no longer trigger any event, I am worried about potential memory leaks. Does either jQuery or the browser take care of that and discard all registered handlers once an element is removed from the DOM?
Even if the element will no longer trigger any event, I am worried about potential memory leaks.
This is very good concern. To answer your question, take a look at $.fn.html implementation. From there you will learn that html will try to clean up stored event data:
// Remove element nodes and prevent memory leaks
if (elem.nodeType === 1) {
jQuery.cleanData(getAll(elem, false));
elem.innerHTML = value;
}
So in this case manually calling .off() is not necessary. However..
You need to remember that you should never ever try to remove elements with native methods like removeChild or setting innerHTML, since in this case there will be a memory leak for sure (if some data is stored, events are registered by jQuery, etc.). In this case it's more reliable to actually deregister event handlers with .off method. Or better use event propagation and instead or html('') use $.fn.remove.
It's better to call jQuery.off before removing your node, especially if it's a one page application which can contains a lot of events registered.
I am fully aware of MutationObserver but what I need is different:
I would like to listen to an element which has been created in the memory, and that specific element can be appended anywhere (thus I do not want to observe everything because it would be an overkill as things gets changed everywhere on the app, all the time).
The listener would fire when the specific element has been inserted to the DOM. just a way to follow a single element instead of watching the whole DOM. it's kinda backwards approach but I think it is the right way to go in my case.
How can this be done? thanks!
$myobject.appendTo('body').trigger('myobserver');
$myobject.on('myobserver',function(){
//do stuff when myobject is added to DOM
});
You could use this CSS trick too: http://www.backalleycoder.com/2012/04/25/i-want-a-damnodeinserted/
I've inherited a jQuery application that does its work by calling AJAX services without leaving the page.
There is a list of items, where when you click on an item the detail of the item is displayed, events attached to the buttons, then the html is disposed and new html will be created, new events attached and so on and so forth.
I was wondering whether JavaScript garbage collection will automatically clean up those events, or do they go in some Map like data structure and create a memory leak. Am I supposed to clean them up explicitly?
If you always bind the same events, you could also use something like jQuery live() or the likes instead of always binding/unbinding them.
Javascript garbage collection will not remove bound events to removed elements. jQuery functions often do depending on what method you use.
In example, .html() or .remove() will remove events and not leak memory. When in doubt you can always use .empty().
In my opinion the .live() discussion is fairly beside the point of memory leaks. The usage of .live() should be done when it makes sense from an architecture standpoint. Unless you need the event to be bound before the element is added to the DOM, or exist after the element is removed (because it may be added again) then .bind() is really the proper and faster method to use. .live() is slower than .bind() because each event must fire at the element, bubble to the document and then bubble back up to the element in order to be processed by .live(), while with .bind it can execute right away.
Also, FYI both .bind() and .live() are deprecated in the newest version of jQuery (1.7). They will still function, but the new syntax is .on(), using delegation to replace .live(). This is because too much .live() really slows down pages because each .live binds another event to the document which must be listened and processed every single event.
if you want to make it easier on the GC and not make him search if it has references , so you should unbind / die all events to the div.