When and why should I remove an event listener? Is it bad, or bad practice to leave all events there? What if a div is hidden, do I still need to remove the event before I hide it?
When and why should I remove an event?
Several reasons:
Old browsers had a memory link where you added event to element and once the element removed from the DOM the event was not removed (memory leak)
Good coding - If you added event - remove it as well
Performance - Less code in memory = faster execution time
Is it bad, or bad practice to leave all events there?
As explain before - no, since the JS engine will know how to take care of that and to remove it.
What if a div is hidden, do I still need to remove the event before I hide it?
No.
Related
This may not be the most clear way of asking what I'm asking but, I have a plugin that manages multiple grouped elements. It is my understanding that a plugin should be capable of destroying itself when the need/want arises. So my question is, is there any kind of hook that either jQuery or JavaScript will fire when a DOM element is removed from the page to assist in JavaScript's garbage collection and avoid memory leaks from event handlers and such? If I am unclear in what I am asking I apologize but I honestly don't know the best way to ask this question
Yes, there is. Although you will need either jQuery UI or to write your own special event. The problem is it only works if the element is removed using jQuery. Aside from that, you would need to use DOM events or the recommended solution - DOM Mutation Observers.
These questions should help you further:
jQuery - Trigger event when an element is removed from the DOM
How to detect element being added/removed from dom element?
By the way, that is the keyword you missed - "event". That's what these "hooks" are called in jQuery/DOM.
I am using jQuery quite heavily in a ASP.NET WebForms application to handle anything client-side that isn't application-critical (eg. on the fly validation, animations, general fluff and pretty stuff).
Within this solution, I am using update panels, so the main page rarely gets refreshed. As such, event listeners can get bound on each asynchronous postback.
With this in mind (or in any other typical circumstances), is there any advantages to using .off to remove event listeners on elements that I know are not going to be active at that time?
Is the standard browser going to suffer much, if any, performance degradation if I leave the event listeners active, or will it only be noticeable at absolute extremes?
Should I just unbind (.off) when I bind (.on) at high-level elements such as body?
What is the best way to handle (if required) unused event listeners in a scenario where they are being bound and unbound multiple times over the life-cycle of a single web-page?
If you have any tests that show if browsers slow down with numerous event listeners, please let me know. Proven numbers would be perfect if anyone has them.
Leaving inactive event listeners will definitely show negative impact on performance. It is definitely a better practice to off unnecessary event listeners.
I would also suggest you to use scope while binding event listeners like
$(".demo").on("click.test", function(){ ... });
Here I have scoped the click event with test so that when I do
$(".demo").off("click.test");
any other demo class having an on click listener will not get switched off.
Do I need to removeEventListener when I change element's style display:none?
Do events effect page performance?
No you don't actually need to, specially if that element is going to be displayed again, because it wouldn't be cool to add/remove the listener every single time. Event listeners are asynchronous, and only impact on performance when they are executed, so since that you're hiding that element (and the user isn't able to interact with it) your listener will not be called as long as it stays hidden, and there will not be any performance impact.
Plus: even if you were completely removing that element using parentEl.removeChild(childEl), you still wouldn't have needed to remove the listeners, because deleting an element will cause all its listeners to be removed as well.
I'm trying to speed up my event registration. Can anyone tell me which will take up the least processing time -
$('#myElement').find('select.foo').on('click', 'option', handler1);
$('#myElement').find('select.bar').on('click', 'option', handler2);
or
$('#myElement').on('click', 'select.foo option', handler1);
$('#myElement').on('click', '.select.bar option', handler2);
I agree with the commenter who said "run some jsPerf tests". The first rule of optimizing is "don't prematurely optimize". Why are you optimizing? Are you having performance problems? If you are, are you sure you've isolated it to this code? That's what profiling will tell you. If it is this code, then you can figure out what method provides more performance.
I suspect that the first version will have higher performance because it will attach the event handlers to the element(s) that are closest to the event generation. The second version attaches the event handlers to elements higher in the DOM tree, so the events will have to propagate before they are caught, and then the event handler has to run a filter to see if the events come from matching elements.
Another way to look at this is that the first version identifies the elements that need listeners at page load time (doing the work then) and the second version identifies the elements that will respond to events as the events occur (spreading the work out and potentially creating more work -- possibly for good reason; see below).
Be very careful, though: often, the second approach is used when elements are inserted dynamically. It's the easiest way to solve the problem of event handlers not being attached to dynamically-added elements. So if you do have dynamically-added elements, then the second version might be your best option, performance considerations notwithstanding.
Attaching the listeners to the same object makes actually attaching the listeners take less time, but the process of catching and handling the events will be slower.
Attaching the listeners closer to the target takes more time, but handlers will fire quicker when the event occurs.
Thanks to this question for the answer - Should all jquery events be bound to $(document)?
After my previous question I heve this one, that might be better.
I need to add a lot of items on the page and I see that sometimes appendChild+fregment is faster than innerHTML. Anyway now I would need to know the fastest way to add elements and add event listeners too.
One way I see is to listen on the window object and then filter.
Pros:
Only add once, then never
No memory trap if you forget to remove events listeners before remove as the event is added on the window object
others?
Cons:
Maybe slower?
Slower as we need to filter the items and will listen for everything everyime... maybe too slow at this point, I don't know.
The other way I know is to listen on the created element.
But with innerHTML I think only works with the window object listener.
Any other oppinions?
thanks
Best practice to handle "multiple" event handlers for "many" elements is event delegation, which is basically what you described.
Create a listener on the closest shared parent (document.body will of course do it for any element, but maybe there is another parent node below that).
Performance should not be the issue there. It's far worse to create like 200 event handler functions instead of one.