Is it safe to assume that for time critical applications it is always better to use function declaration or function expressions, instead of inline functions in heavily executed callbacks?
Consider following test program:
var x;
var count3 = function count3() {
x++;
}
var count2 = function () {
x++;
}
function count() {
x++;
}
function execute(cb) {
cb();
}
x = 0;
var a = new Date().getTime();
for (var i = 0; i < 100000000; i++) {
execute(function named() {
x++;
})
}
a = new Date().getTime() - a;
console.log("Named inline function: " + a);
x = 0;
a = new Date().getTime();
for (var i = 0; i < 100000000; i++) {
execute(function () {
x++;
})
}
a = new Date().getTime() - a;
console.log("Anonymous inline function: " + a);
x = 0;
a = new Date().getTime();
for (var i = 0; i < 100000000; i++) {
execute(count);
}
a = new Date().getTime() - a;
console.log("Function declaration: " + a);
x = 0;
a = new Date().getTime();
for (var i = 0; i < 100000000; i++) {
execute(count2);
}
a = new Date().getTime() - a;
console.log("Anonymous function expression:" + a);
x = 0;
a = new Date().getTime();
for (var i = 0; i < 100000000; i++) {
execute(count3);
}
a = new Date().getTime() - a;
console.log("Named function expression:" + a);
This gives following output (in ms):
Named inline function: 2347
Anonymous inline function: 2121
Function declaration: 771
Anonymous function expression:750
Named function expression:752
Function declaration and function expressions are 3 times faster than inline functions on my humble laptop.
Yes, this can be generalized. Technically the function expression in the loop body is re-evaluated to a new function object every loop turn. As your tests confirm, this is noticeable slower (for millions of iterations) than having one "static" function defined outside the loop. Whether the function is named or not does not really matter, it has a very little overhead in introducing another variable in the execution contexts.
However, this is only relevant when the function really is declared inside the iteration, as in your examples. If you instead had a
function executeAll(cb) {
for (var i = 0; i < 100000000; i++) {
cb();
}
}
then there be no difference between
executeAll(function() { x++; });
and
function increase() { x++; }
executeAll(increase);
since the cb argument is the "static" reference to the one function.