7 ms·
Always return on events is faster, but why?
- dominicglenn 13y agoI posted it on the page as well: Doesn't just calling return from an event equate to returning boolean false, which means you are invoking the effects of preventDefault() and stopImmediatePropagation() thus explaining why with return it's faster as the event stops bubbling immediately?
- EmielMols 13y agoNo. It equates to returning undefined, which is the same as having no return statement at all.
- dreen 13y agoAlthough it obviously isn't quite the same. I wonder what is the test result for no return vs return true
- Tarang 13y agoStill faster, check revision 6 http://jsperf.com/always-return-on-jquery-events/6 http://jsperf.com/always-return-on-jquery-events/6 revision 7 http://jsperf.com/always-return-on-jquery-events/7 http://jsperf.com/always-return-on-jquery-events/7. Just return vs return true (faster). But as smilekzs points out revision 3 this might not be about the return statement.
- lucideer 13y ago!!undefined === false
- bengillies 13y agoright. undefined is falsy, but it's quite different to false (i.e. undefined !== false)
- lucideer 13y agotrue, but a boolean return value is expected for event listener callbacks.
- Stratoscope 13y agoThat's not quite how it works. jQuery checks specifically for false with an === comparison. It doesn't do anything like a !! on the return value to convert it to boolean true or false. It only calls stopPropagation and preventDefault when the return value is false, not just any falsy value. I posted the jQuery code in a previous comment; take a look at that and you can see how it works.
- al2o3cr 13y agoFWIW, the underlying jQuery code explicitly tests for false with ===: https://github.com/jquery/jquery/blob/a5037cb9e3851b171b49f6d717fb40e59aa344c2/src/event.js#L317 https://github.com/jquery/jquery/blob/a5037cb9e3851b171b49f6... So returning undefined does NOT stop propagation.
- lukashed 13y agoDoesn't a return without argument return false and thus have the same effect as preventDefault()? That would explain the difference, since the events are not "bubbling up".
- Tarang 13y agoreturn without return false is just like breaking out of a method i think.. The events would still bubble since false isn't returned
- deleted 13y ago[deleted]
- K0nserv 13y agoAn empty return statement has the return value undefined which is falsy. As lukashed said jQuery most likely interprets this as false and stop propagation of the event, however using an empty function also has the return value undefined so both cases stops propagation. Both versions have the same return value as illustrated by this fiddle http://jsfiddle.net/QHxJ3/ http://jsfiddle.net/QHxJ3/
- Tarang 13y agoInteresting, I would have never thought the js interpreter would interpret both as being === even though the two functions are different.
- Stratoscope 13y agoThe two functions are different, but their return values are identical. The === is comparing the return values. Consider this example: function onePlusOne() { return 1 + 1; } function two() { return 2; } alert( onePlusOne === two ); // false, not the same function alert( onePlusOne() === two() ); // true, same value
- Stratoscope 13y ago> As lukashed said jQuery most likely interprets [undefined] as false and stop propagation of the event... No, it doesn't. jQuery uses a strict test for false and does not stop propagation for other falsy return values from an event listener. The documentation could be more clear on this point. All it says is: "Returning false from an event handler will automatically call event.stopPropagation() and event.preventDefault()." http://api.jquery.com/on/#event-handler http://api.jquery.com/on/#event-handler Here's the code that does this check: if ( ret !== undefined ) { if ( (event.result = ret) === false ) { event.preventDefault(); event.stopPropagation(); } } https://github.com/jquery/jquery/blob/master/src/event.js#L397 https://github.com/jquery/jquery/blob/master/src/event.js#L3... Reading that code, it almost seems redundant at first to have a !== undefined check when the === false is already a strict comparison. But there is that assignment hidden inside the if expression. So the code is really the same as this more clearly written version: if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } This would also have the same effect: if ( ret !== undefined ) { event.result = ret; } if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } These all do the same thing: set event.result only if ret is not undefined, and then call preventDefault and stopPropagation only if ret is false (and not just a falsy value).
- andremedeiros 13y agoIf you use the browser's "onclick" or "onmouseout" properties instead of the jQuery event calls, the result is very similar: http://jsperf.com/always-return-on-jquery-events/5 http://jsperf.com/always-return-on-jquery-events/5
- smilekzs 13y agoRevision 3 revealed that it's not the `return` that made the difference -- it's the jsperf runner failing to introduce sufficient time gap between testsuites for it to "settle down"...
- deleted 13y ago[deleted]
- eulerphi 13y agoIt's not the jsperf runner, ie. any "settling" of GC sweeping, or anything of that nature. It's surprisingly the location of the DOM elements. See here, I've swapped the two elements, and now the result is _backwards_ http://jsperf.com/always-return-on-jquery-events/21 http://jsperf.com/always-return-on-jquery-events/21 Can anyone with knowledge of the webkit internal DOM id-based key/hashtable shed light on this? I'm guessing that for the 2nd child, when it's propagating upwards, it has to hit 1 more element -- that is, if it must reach the first child to get the parent. I'd hope that the structure is more optimized than a simple crawl to the first node to go upwards. EDIT: Actually, I'm wrong. I edited the test to have 6 divs, and re-arranged the order of the tests. The tests still come in performance-wise from first-to-last, first performing the best. I really don't know what to think now.
- deleted 13y ago[deleted]
- Sidnicious 13y agoeulerphi: FYI you're hellbanned
- Cthulhu_ 13y agoIsn't the idea of hellbanning that people don't realize they are? Kinda defeats the purpose if you notify them of it. If HN wanted people to know they've been silenced, they would be given an error message. So, don't tell people. It's also spamming the comment with offtopic remarks.
- 13y ago
- angelomichel_nl 13y agoAllright.. So most likely, return or no return does not make any difference. Or at least that is the feeling I get from Colin's revision (3). Myth busted? Or is there another tail to the story.
- callum85 13y agoBoth functions return "undefined". They should be identical after JIT compilation. The only thing I can imagine taking longer would be the compilation step itself... but I had always assumed jsPerf didn't work like this, i.e. I thought it would wrap the test code in a 'for' loop and then eval the whole loop, rather than doing the eval call inside the loop.
- kiplinger 13y agoIs there some low level checking by the js engine to see if it should stop processing the function if there is no return? Or, to put it another way, does adding the return explicitly tell the engine, "ok we're done here", as opposed to a small amount of processing required by the engine to determine that for itself?
- hqm42 13y agoRevision 22 revealed that something went terribly wrong...
- Tichy 13y agoMaybe because "some_el_2" is lower down in the DOM tree? I think at least the experiment should be run with reversed IDs.
- recentdarkness 13y agoIt shouldn't matter because if you swap the execution order, the 'no return' can be faster too in that test.
- rrzar 13y agoIn fact it's not really faster, if you run the test several times the results are similar. It's the same thing if you compare the selectors $(this) and $((((this)))); I don't know why, but the problem must come from jsperf. Thats why when I use this tool I always run it at least 5 times to be sure.
- mraleph 13y agoAnswer is simple: you are adding more and more listeners as jsPerf runs your test case. One of the most important things to remember while using jsPerf is that setup phase can and will be executed multiple times. As the result the list of listeners attached to the DOM node is growing and this in turn slows down the event dispatch. "No return" case is run second so the list of listeners is already large and thus it is slower than "return case". You should either unregister listeners in tear down phase or register them only once at global initialization time. Here is the fixed variant: http://jsperf.com/always-return-on-jquery-events/28 http://jsperf.com/always-return-on-jquery-events/28 [also from the JavaScript VM point of view function () { } and function () { return; } are completely the same]
- esailija 13y agoAlso another mistake here is the classical "if you want to measure x, don't measure y". If the OP wanted to measure function with or without return , even without realizing how futile that is, they still should not include things like jQuery.
- sesqu 13y agoWell, before the GP post, my takeaway was that it's better to return when using jQuery. The justification for this would have been some magic, which is the sole purpose of jQuery, slowing stuff down. And the web being as it is, testing with jQuery might even be more useful than testing without it.
- esailija 13y agoThat is a common fallacy and benchmarking anti-pattern, and it really enrages me that some people look at the completely incorrect results and justify it with "I am going to be using this with jQuery so why shouldn't I add some jQuery method calls". And you are denying this despite the "fixed" js perf showing different results e.g. on chrome 29. You should read http://zedshaw.com/essays/programmer_stats.html http://zedshaw.com/essays/programmer_stats.html
- elwell 13y agothe first time i ran the tests "no return" was faster