views:

1386

answers:

14

I've been wondering, is there a performance difference between using named functions and anonymous functions in Javascript?

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = function() {
        // do something
    };
}

vs

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

The first is tidier since it doesn't clutter up your code with rarely-used functions, but does it matter that you're re-declaring that function multiple times?

A: 

If the first is cleaner to you (people will debate that I'm sure) then use that.. don't worry about performance. If it's clean code vs 2x code speed, clean code still wins imo.

SCdF
+1  A: 

As a general design principle, you should avoid implimenting the same code multiple times. Instead you should lift common code out into a function and execute that (general, well tested, easy to modify) function from multiple places.

If (unlike what you infer from your question) you are declaring the internal function once and using that code once (and have nothing else identical in your program) then an anonomous function probably (thats a guess folks) gets treated the same way by the compiler as a normal named function.

Its a very useful feature in specific instances, but shouldn't be used in many situations.

Tom Leys
+2  A: 

I found this interesting: http://weblog.raganwald.com/2007/08/ruminations-about-performance-of.html

I would think it depends on the browser though really.

Arthur Thomas
+1  A: 

I wouldn't expect much difference but if there is one it will likely vary by scripting engine or browser.

If you find the code easier to grok, performance is a non-issue unless you expect to call the function millions of times.

Joe Skora
+3  A: 

Try!

You already got the two snippets to run, just add a timer around them and compare.

hehe i was just thinking that as I was writing it... :p
nickf
A: 

What will definitely make your loop faster across a variety of browsers, especially IE browsers, is looping as follows:

for (var i = 0, iLength = imgs.length; i < iLength; i++)
{
   // do something
}

You've put in an arbitrary 1000 into the loop condition, but you get my drift if you wanted to go through all the items in the array.

+1  A: 

Here's my test code:

var dummyVar;
function test1() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = myFunc;
    }
}

function test2() {
    for (var i = 0; i < 1000000; ++i) {
        dummyVar = function() {
            var x = 0;
            x++;
        };
    }
}

function myFunc() {
    var x = 0;
    x++;
}

document.onclick = function() {
    var start = new Date();
    test1();
    var mid = new Date();
    test2();
    var end = new Date();
    alert ("Test 1: " + (mid - start) + "\n Test 2: " + (end - mid));
}

The results:
Test 1: 142ms Test 2: 1983ms

It appears that the JS engine doesn't recognise that it's the same function in Test2 and compiles it each time.

nickf
A: 

@nickf

That's a rather fatuous test though, you're comparing the execution and compilation time there which is obviously going to cost method 1 (compiles N times, JS engine depending) with method 2 (compiles once). I can't imagine a JS developer who would pass their probation writing code in such a manner.

A far more realistic approach is the anonymous assignment, as in fact you're using for your document.onclick method is more like the following, which in fact mildly favours the anon method.

Using a similar test framework to yours:


function test(m) { for (var i = 0; i < 1000000; ++i) { m(); } }

function named() {var x = 0; x++;}

var test1 = named;

var test2 = function() {var x = 0; x++;}

document.onclick = function() { var start = new Date(); test(test1); var mid = new Date(); test(test2); var end = new Date(); alert ("Test 1: " + (mid - start) + "ms\n Test 2: " + (end - mid) + "ms"); }

annakata
+25  A: 

The performance problem here is the cost of creating a new function object at each iteration of the loop and not the fact that you use an anonymous function:

for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = function() {
        // do something    
    };
}

You are creating a thousand distinct function objects even though they have the same body of code and no binding to the lexical scope (closure). The following seems faster, on the other hand, because it simply assigns the same function reference to the array elements throughout the loop:

function myEventHandler() {
    // do something
}

for (var i = 0; i < 1000; ++i) {
    myObjects[i].onMyEvent = myEventHandler;
}

If you were to create the anonymous function before entering the loop, then only assign references to it to the array elements while inside the loop, you will find that there is no performance or semantic difference whatsoever when compared to the named function version:

var handler = function() {
    // do something    
};
for (var i = 0; i < 1000; ++i) {    
    myObjects[i].onMyEvent = handler;
}

In short, there is no observable performance cost to using anonymous over named functions.

As an aside, it may appear from above that there is no difference between:

function myEventHandler { /* ... */ }

and:

var myEventHandler = function { /* ... */ }

The former is a function declaration whereas the latter is a variable assignment to an anonymous function. Although they may appear to have the same effect, JavaScript does treat them slightly differently. To understand the difference, I recommend reading, “JavaScript function declaration ambiguity”.

Atif Aziz
A: 

a reference is nearly always going to be slower then the thing it's refering to. Think of it this way - let's say you want to print the result of adding 1 + 1. Which makes more sense:

alert(1 + 1);

or

a = 1;
b = 1;
alert(a + b);

I realize that's a really simplistic way to look at it, but it's illustrative, right? Use a reference only if it's going to be used multiple times - for instance, which of these examples makes more sense:

$(a.button1).click(function(){alert('you clicked ' + this);});
$(a.button2).click(function(){alert('you clicked ' + this);});

or

function buttonClickHandler(){alert('you clicked ' + this);}
$(a.button1).click(buttonClickHandler);
$(a.button2).click(buttonClickHandler);

The second one is better practice, even if it's got more lines. Hopefully all this is helpful. (and the jquery syntax didn't throw anyone off)

matt lohkamp
A: 

@annakata

You've missed what I've been trying to test. Your example just calls two functions identical in every way except for how they were first defined. What I was asking was whether or not it was a performance hit to use anonymous functions (which are defined multiple times if used in a loop) vs a named function (defined only once). It might seem obvious, but I thought perhaps the JS engine would compile it only once or something.

I'll admit my test was slightly fatuous (I'll also admit that I had to look that up), because it didn't strictly test what I was initially asking (it included running time for the functions). I'll modify my other answer to show the updated code.

nickf
A: 

YES! Anonymous functions are faster than regular functions. Perhaps if speed is of the utmost importance... more important than code re-use then consider using anonymous functions.

There is a really good article about optimizing javascript and anonymous functions here:

http://dev.opera.com/articles/view/efficient-javascript/?page=2

Chris Tek
A: 

@nickf

(wish I had the rep to just comment, but I've only just found this site)

My point is that there is confusion here between named/anonymous functions and the use case of executing + compiling in an iteration. As I illustrated, the difference between anon+named is negligible in itself - I'm saying it's the use case which is faulty.

It seems obvious to me, but if not I think the best advice is "don't do dumb things" (of which the constant block shifting + object creation of this use case is one) and if you aren't sure, test!

annakata
A: 

Anonymous objects are faster than named objects. But calling more functions is more expensive, and to a degree which eclipses any savings you might get from using anonymous functions. Each function called adds to the call stack, which introduces a small but non-trivial amount of overhead.

But unless you're writing encryption/decryption routines or something similarly sensitive to performance, as many others have noted it's always better to optimize for elegant, easy-to-read code over fast code.

Assuming you are writing well-architected code, then issues of speed should be the responsibility of those writing the interpreters/compilers.

pcorcoran