0

Context

I am building a Redux application, and would like click and mousemove event handlers to change depending on application state.

To accomplish this, I am planning to attach a single click and single mousemove handler to the document. These will belong to a scope that subscribes to the Redux store, and knows the relevant state.

I see two strategies for implementing the handlers:

  1. Use a switch statement against the relevant state variable. This switch would have to be called for each fired event.
  2. Reference internal (to the scope) scope._clickHandler and scope._moveHandler properties that swap out their referents whenever the state is updated.

Question 1:

If I choose Strategy 2, I will want my mousemove handler to do nothing most of the time. But mousemove gets fired a lot! What is the most performant no-op function that could be bound to the scope._moveHandler property?

Question 2:

In the best case (w/r/t Question 1), would Strategy 2 be more performant than Strategy 1, assuming the switch statement used in Strategy 1 has to test between 10 and 100 cases?

Clarification

On this approach, one "delegating" function will always be called when an event fires. That function will do different thing depending on a state property, either by matching that state in a switch or simply by having different "delegee" functions bound as the state.

Question 1 asks about the optimal do-nothing "delegee" function, while Question 2 asks about the performance penalty incurred by having a large switch block in a mousemove callback.

If we as a community agree with @nnnnnn's intuition that function(){} is as good as it gets for a no-op, my question becomes:

Which is worse for performance: the overhead for the no-op function call, or the equality comparisons in a switch block?

A. Vidor
  • 2,502
  • 1
  • 16
  • 24
  • 2
    1. Check if it's not `null`, then call. No call is the cheapest call. – zerkms Jul 29 '16 at 00:03
  • 1
    *"What is the most performant no-op function"* - If you assume a function *must* be called at all then wouldn't the most performant just be an empty function? – nnnnnn Jul 29 '16 at 00:03
  • You could also set the event programmatically (from http://stackoverflow.com/questions/5745191/setting-events-programmatically); whenever you need to change what `onclick` or `onmousemove` do, just get the element and set those properties (literally `element.onclick` or `element.onmousemove`) to the new function – Doc Jul 29 '16 at 00:05
  • @this-vidor well, if you don't have a handler - then don't attach anything at all to the component's `onMouseMove`. – zerkms Jul 29 '16 at 00:06
  • @zerkms The purpose of this overall approach is to avoid having to manage adding/removing handlers— and therefore having to keep track of references to event handlers. But in other contexts you are of course correct. – A. Vidor Jul 29 '16 at 00:09
  • @zerkms This is also not a React app, there is no component for me to re-render with a null or non-null `onMove` prop. Just Redux! As stated in the question, these event listeners are added to the `document`. – A. Vidor Jul 29 '16 at 00:10
  • @nnnnnn That is exactly what I'm asking! Something like `function(){}` seems like a good candidate, but so does `function(){ return false; }`. And I can't set aside the possibility that JavaScript (or certain engines) have some builtin no-op symbol. – A. Vidor Jul 29 '16 at 00:15
  • 1
    Returning `false` from an event handler actually has a specific effect that you don't want: it cancels the event's default behaviour. – nnnnnn Jul 29 '16 at 00:22
  • @nnnnnn So is your answer to **Question 1**: `function(){}` ? – A. Vidor Jul 29 '16 at 00:25
  • 1
    Yes, that's my common-sense, no-research-done-but-I-don't-see-how-anything-else-could-be-faster answer. – nnnnnn Jul 29 '16 at 00:27
  • Something I've found useful when binding events for mousemove is to wrap them in lodash's throttle function: https://lodash.com/docs#throttle – John Jul 29 '16 at 01:45

0 Answers0