An example would be if you had multiple inputs, each of which effect a completely different process, (perhaps one changes a div's width, while another sends ajax request for predictive search), would you bind a single event use a switch statement to call the process functions, or set multiple eventListeners bound to each input element? Part of the reason for me asking is I'm not sure of the performance implications of multiple event listeners, but even if those are negligible, readability and code maintenance considerations could still impact on the answer.Some considerations:a) Would it depend on the expected frequency of use?b) would a common event such as mousemove be better with one approach, while input be better with another?c) if the switch approach is deemed better, what is the maximum size/complexity that the switch statement should be allowed to grow to.
Should I reduce event listeners by making functions more complex?
design patterns;javascript;event;dom
The Buzz Word you are looking for, which might help in your search for answers, is JavaScript Event Delegation.There are two basic kinds of event delegation:Component delegation: One listener for each event is registered per component on the pageFront Controller delegation: One listener for each event is registered for all components, and then attributes within the HTML are used for dynamic dispatch to functions or objects representing each component.The kind you are questioning is the Front Controller variety.Front Controller Event DelegationA working example of this is a library I wrote called Oxydizr. It uses a custom HTML attribute data-actions to dispatch the handler to the proper controller object. While not a switch statement, it boils down to the same basic logic as you are proposing.This layer of abstraction is useful if you have an unknown number of components that will be used on each page, and you don't want to write additional JavaScript code to wire up your UI to event listeners.The increase in complexity is balanced out by the ease of extensibility and implementation. No more do you need to write HTML code and a bunch of JavaScript code specific to that HTML structure. Add a splash of HTML attributes and event delegation on a common root element handles calling the proper function.a) Would it depend on the expected frequency of use?Yes. If you have a lot of events to handle, or a lot of elements for which you need to handle interactions, the Front Controller flavor of event delegation is a good fit. The added benefit here is, if done right, adding new components is very easy.b) would a common event such as mousemove be better with one approach, while input be better with another?Actually, since the mousemove event can fire upwards of 50 times per second. To maintain a smooth experience for the user your Front Controller and handler must execute faster than 20 milliseconds. That's not much time for an interpreted language! For that reason, spammy events like mousemove and scroll are better handled on their own outside of event delegation of any sort. This leads into the performance implications of this pattern.Event Delegation PerformanceYou do take a hit to performance at runtime, but gain performance at page load. The more nodes in the document tree, the more apparent the gain in page load performance becomes.Libraries like jQuery, and native DOM API's like querySelectorAll allowing you to target elements by CSS selector have a hidden dark side: unless the browser optimizes for certain selectors, the browser basically has to iterate over every element in the document tree when getting elements by CSS selector. This is especially noticeable at page load for larger pages, and becomes even more noticeable on mobile devices with slower processors or less RAM. So, code like:var elements = document.querySelectorAll(.foo);for (var i = 0; i < elements.length; i++) {    elements[i].addEventListener(...);}Gets increasingly costly in execution time as your web application grows.It is much faster at page load to add listeners to one element. My favorite is document.documentElement, because it references the <html> element, and exists from the moment JavaScript begins executing. No need to wait for a DOMContentLoaded event or DOM ready event.You do incur a runtime performance hit for two reasons:The event is handled after bubbling up from the source element, rather than being handled at the source element. It's been my experience that this is minimal, if not so small you can't accurately measure the impact in JavaScript.The event delegate, be it a Front Controller or an individual component, must loop in JavaScript from the source element up the document tree for each invocation of the event just to see if it is something it can handle.These two items do reduce performance while the user is interacting with the page. Again, it's a small reduction, so avoiding event delegation for these two reasons is a Premature Optimization.Dynamic Dispatch with a Front Controllerc) if the switch approach is deemed better, what is the maximum size/complexity that the switch statement should be allowed to grow to.The mere fact you are questioning this tells me that a switch statement is the wrong way to go about this. Don't use a switch statement. You need to annotate your HTML with some custom data-* attributes to make extending this easy, and cost zero work.<button type=button        data-action=confirm        data-confirm=Are you sure?>    Delete Item?</button>In this naive implementation you would register a listener on a Front Controller:frontController.addListener(confirm, function(event) {    if (!confirm(event.target.getAttribute(data-confirm)) {        event.preventDefault();    }});Extending this for another component is easy:frontController.addListener(removeItem, function(event) { ... });The implementation of this example:var frontController = {    listeners: {},    addListener: function(actionName, callback) {        this.listeners[actionName] = callback;    },    handleClick: function(event) {        var listeners = frontController.listeners,            action = event.target.getAttribute(data-action);        if (listeners[action]) {            listeners[action](event);        }    }};document.documentElement.addEventListener(click, frontController.handleClick, false);You'll see that there is no need for a switch statement, because data embedded in the HTML document allows you to write one decision structure to handle all components. This is where you want to be if implementing the Front Controller pattern for event delegation.So, Should I reduce event listeners by making functions more complex?Yes, if:You expect to add many more componentsYou don't want to write code to add event listenersYou don't want to write code to remove event listeners for elements that have been removed from the document tree (unless you like memory leaks)No, if:You don't need to do a lot of JavaScript workYou don't mind writing code to add event listeners when elements are added to the page dynamicallyYou don't care about memory leaks from removed elements that still have active event listeners.And yes, there are times when you don't care about memory leaks. If the page isn't used for very long, a memory leak might not be a big deal. For Single Page Applications... I hope you have LOTS of RAM.