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.
Related
In Vaadin when readding a component that was removed previously will create a new element in the DOM.
Lets look at it in detail
Button button = new Button("test");
button.getElement().executeJs("""
this.addEventListener("click", event => {
alert("hello");
});
""");
add(button);
now after some event on the server we decide to remove the component from the view. So the corresponding element in the DOM gets removed.
then after another event we add the button component again. so vaadin creates a new Element on the client and adds this to the DOM. (the new element is missing the eventlistener)
What I would expect to happen is that vaadin reuses the same element that existed before. But it does not. normally this would not really matter, but in our case we added a eventlistener with js. (yes we could add eventlisteners on the javaside, but let’s suppose that we really need to do it in js because we want to execute some code on the client)
why is vaadin doing this, and is there an option so vaadin uses always the same element.
In pure JS I could easily just create a lookup table with the element that I removed, and then later use the elements in the lookup table to add them again to the DOM. Doing this would keep all the event listeners for the element.
What really perplexes me, is that even though the element in the DOM is different everytime, the Element I get with component.getElement() is always the same. Isn’t this element supposed to represent the element on the clientside?
Of course we could just run the same js on the element everytime we add the element to the view, but that is quite cumbersome.
Is vaadin doing this because of performance reasons. What are your explanations for this behaviour?
This is indeed a mechanism to avoid leaking memory. A mechanism based on server-side reference tracking would be significantly more complex, work with a delay (because the reference is cleared only when GC runs), and make it more difficult for the developer to control what happens. The current design makes it easy for the developer to choose what should happen: hide to preserve it in the browser, detach to let it be garbage collected.
I could also clarify that the same DOM element is reused in cases when the component is detached and then attached back again during the same server visit.
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 am trying to get rid of detached DOM Elements and having a hard time finding the cause of the leak.
Can somebody help me understand what native link from DOM wrapper stored in the detached window property is. What does it mean native link?
https://developer.chrome.com/devtools/docs/heap-profiling-dom-leaks
By tracing paths to window objects, it can be observed, that the
detached DOM tree is referenced as the native link from the DOM
wrapper stored in the detached window property. To confirm this, do
the following...
Any help will be appreciated!
In the example you have linked, there is a variable called 'detached' that is being created as a global on the window object.
window.detached
They then go on to generate an entire DOM tree with lots of children and extra data and they store that reference in the window.detached variable. It is not however actually mounted into the DOM.
The block that you have quoted is just pointing out that if you have any dom nodes you've generated that still have an active reference pointing to them (in this case the reference is window.detached) then they will not be garbage collected.
They go to the trouble of pointing this out because some people may expect that as soon as you unmount a tree of nodes from the DOM that they are candidates for GC. They're pointing out that what really matters is if there is still a reachable reference to the item. If not, it will be GC'ed. Otherwise it will hang around.
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.
<div id="target">
...
</div>
$('#target').html('') will remove the content,but how to check if the listeners or anything else that holds memory is removed at the same time?
Standard JavaScript defines no means to instrument the interpreter's garbage collector, so I don't think this is possible.
However, since removing nodes is not an uncommon operation, I would not worry about browsers leaking memory in this case. Indeed as Piskvor said, the memory is probably not released immediately, but when the garbage collector eventually runs.
I am not sure how you can detect a leak within a JavaScript (using JavaScript). but there are tools available to detect the leaks in JavaScript
sIEve
IEJSLeaksDetector2.0.1.1
I'm no expert on this, but since you're using jQuery you should use $('#target').empty(). This detaches all event handlers before removing the child elements. When these are collected is up to the browser, but this ensures that they will get collected when the time comes. You can also use $.remove() to get rid of the selected element and all children.
http://api.jquery.com/empty