Does use of anonymous functions affect performance?

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?

Answers:

Answer

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”.

The actual execution time for any approach is largely going to be dictated by the browser's implementation of the compiler and runtime. For a complete comparison of modern browser performance, visit the JS Perf site

Answer

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.

Answer

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.

Answer

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.

Answer

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.

Answer

Where we can have a performance impact is in the operation of declaring functions. Here is a benchmark of declaring functions inside the context of another function or outside:

http://jsperf.com/function-context-benchmark

In Chrome the operation is faster if we declare the function outside, but in Firefox it's the opposite.

In other example we see that if the inner function is not a pure function, it will have a lack of performance also in Firefox: http://jsperf.com/function-context-benchmark-3

Answer

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.

Answer

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)

Answer

@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!

Answer

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

Answer

@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");
}
Answer

As pointed out in the comments to @nickf answer: The answer to

Is creating a function once faster than creating it a million times

is simply yes. But as his JS perf shows, it is not slower by a factor of a million, showing that it actually gets faster over time.

The more interesting question to me is:

How does a repeated create + run compare to create once + repeated run.

If a function performs a complex computation the time to create the function object is most likely negligible. But what about the over head of create in cases where run is fast? For instance:

// Variant 1: create once
function adder(a, b) {
  return a + b;
}
for (var i = 0; i < 100000; ++i) {
  var x = adder(412, 123);
}

// Variant 2: repeated creation via function statement
for (var i = 0; i < 100000; ++i) {
  function adder(a, b) {
    return a + b;
  }
  var x = adder(412, 123);
}

// Variant 3: repeated creation via function expression
for (var i = 0; i < 100000; ++i) {
  var x = (function(a, b) { return a + b; })(412, 123);
}

This JS Perf shows that creating the function just once is faster as expected. However, even with a very quick operation like a simple add, the overhead of creating the function repeatedly is only a few percent.

The difference probably only becomes significant in cases where creating the function object is complex, while maintaining a negligible run time, e.g., if the entire function body is wrapped into an if (unlikelyCondition) { ... }.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.