4

Just a small theoretical performance question:

if I have something like:

$(".somediv").each(function() {
   // perform some heavy stuff here
});

Would the execution of the code not be faster if I refactored the code of the anonymous function to a named function like :

f = function() {
   // perform some heavy stuff here
};

$(".somediv").each(f);

Somehow I have this irrational doubt that tells me that perhaps the anonymous function is re-created each time within the each loop?

witwit
  • 101
  • 7
  • 2
    irrational doubt is irrational – Roest Aug 06 '12 at 07:20
  • try to remove any thing that is not needed in the loop for your "perform some heavy stuff here" eg. declared variables should be outside the loop. There is not much difference between the two options you have mentioned. – Clinton Ward Aug 06 '12 at 07:25
  • This is what tools like http://jsperf.com/ were designed to answer. Also, the answer may change from browser to browser! – clee Aug 06 '12 at 07:23

4 Answers4

3

If you are concerned about performance, then you should not use .each(). It is much faster to iterate the contents of a collection with a for loop or a while loop and have no function call at all than it is to use .each() with its resulting function call for each item.

In answer to your question, the anonymous function will not be any slower than the named function. The differences are resolved at parse time before run-time.

This jsPerf shows a plain for loop as almost 10x faster than .each(): http://jsperf.com/each-vs-for-loop-mine.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Can you point to some reference regarding the resolving of those differences at parse time instead of at run-time? Would [this answer](http://stackoverflow.com/a/81329/1081396) make sense then? – Alvaro Jul 11 '16 at 11:35
1

Let's consider the code (jquery 1.7.1):

// "public" each
each: function( callback, args ) {
    return jQuery.each( this, callback, args );
}

// "local" each
each: function( object, callback, args ) {
    // [...]

    if (args) {
        // [ args is for internal use ...]
    // A special, fast, case for the most common use of each
    } else {
        if (isObj) {
            for (name in object) {
                if (callback.call(object[name], name, object[name]) === false) {
                    break;
                }
            }
            // [...]

As you can see, callback is referenced and used directly. There is no copying the callback function. Nevertheless, your suggested workaround would produce the same behaviour within jQuery, if jQuery was to copy functions.

Note: In JavaScript, functions are objects. There is no "irrational" reason for one function declaration syntax to behave differently than another. The only difference is scope. Your suggested workaround would make the function a global one, whereas the other anonymous function is "local" to the each call

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
0

It's not recreated, it's created once and a reference is passed to the function $.each(). That function then calls the anonymous function via its reference.

If there was a difference, I don't think it'd be significant enough to warrant using a different pattern besides what is easiest to comprehend when someone else is reading your code. If a performance issue pops up in your code, measure it and find the bottleneck. It's almost certainly not from something like this.

alex
  • 479,566
  • 201
  • 878
  • 984
0

Here's a comparison of .each() and a for loop:

http://jsperf.com/jquery-each-perf-test2/2

Nicholas Albion
  • 3,096
  • 7
  • 33
  • 56
  • It is not advisable to use `console.log()` in the middle of a performance test as it's not guaranteed to be a constant amount of overhead. – jfriend00 Aug 06 '12 at 07:32