2

In the following jsperf: http://jsperf.com/defined-function-vs-in-loop-function/3

You will notice that this code:

for (var i = 0; i < loops; i++) {
   function func(a, b) {
    return a + b;
  };
  func(i, i);
}

Performs on par with this code:

function declaredFn(a, b) {
    return a + b;
};


for (i = 0; i < loops; i++) {
    declaredFni, i);
}

But this code:

for (i = 0; i < loops; i++) {
  var func = function(a, b) {
    return a + b;
  };
  func(i, i);
}

is significantly slower then this code:

var expfunc = function(a, b) {
  return a + b;
};
for (i = 0; i < loops; i++) {  
  expfunc(i, i);
}

Why? What is happening internally?

phantom
  • 1,457
  • 7
  • 15
j03m
  • 5,195
  • 4
  • 46
  • 50

2 Answers2

8

If you define a function using the function fn() {} declaration, it gets hoisted to the top. Therefore, this code:

for (var i = 0; i < loops; i++) {
   function func(a, b) {
    return a + b;
  };
  func(i, i);
}

is exactly equivalent to this code:

function declaredFn(a, b) { return a + b; };

for (i = 0; i < loops; i++) { declaredFn(i, i); }

because the function declaration gets hoisted to the top.

However, var fn = function() {} expressions do not get hoisted, so you end up defining the function all over on every single loop.

See this answer for more info.

Community
  • 1
  • 1
soktinpk
  • 3,778
  • 2
  • 22
  • 33
  • It seems to depend on the JS implementation. The test shows that for FireFox it is significantly slower then other versions. – freakish Nov 02 '14 at 22:33
  • @freakish That's probably because Firefox supports a third type of function creation: function statements. They behave the same as function expressions, so they're created within the loop, not before. – Marcel Korpel Nov 02 '14 at 22:35
  • But wouldn't your function statement be a function declaration on any system not supporting the function-statement-extension? In this case it would be a wrong place for a function definition since it's only allowed in `Program`- or `FunctionBody`-Level. – delbertooo Nov 02 '14 at 22:45
  • @delbertooo Yes that's true. It's wrong in theory but not in practice because most (some) browsers support it (unless you turn on strict mode -- if you turn on strict mode, then declaring a function in a loop using `function fn(){}` method will give a syntax error). – soktinpk Nov 02 '14 at 22:47
0

In the snippet

for (i = 0; i < loops; i++) {
  var func = function(a, b) {
    return a + b;
  };
  func(i, i);
}

you are assigning a function to a variable, which will be available in the rest of the current scope. As you are doing this in a loop, the function is defined and assigned many times, therefore consuming more time than in the other cases you mentioned.

Tobi
  • 2,001
  • 2
  • 27
  • 49
  • 1
    "you are assigning a function to a variable" --- even if you remove assignment performance will stay the same – zerkms Nov 02 '14 at 22:35
  • I don't think (but didn't test it), that performance will stay exactly the same, but I guess you are right, that the function definition takes much longer. – Tobi Nov 02 '14 at 22:38
  • "I don't think (but didn't test it), that performance will stay exactly the same" --- well, try then – zerkms Nov 02 '14 at 22:39
  • Sry, didn't really think, when I wrote my last comment: If you remove the assignment, the function is declared only once, if you assign it to a variable, it's defined in every single loop. So it's substantially different code and performance does not stay the same. – Tobi Nov 02 '14 at 22:48
  • 1
    it's not an assignment that is slow since assignment is virtually free. Convert it to IIFE, there will be no assignment but it will be slow. – zerkms Nov 02 '14 at 22:50
  • Cause if you use a selfexecuting-anonymous-function the definition will be executed every time, as no function is declared, which is available in the current scope. – Tobi Nov 02 '14 at 22:54
  • it will be executed multiple times not because it's IIFE, and not because of there is an assignment, but because it's a function expression. This statement "you are assigning a function to a variable ... s you are doing this in a loop" is basically incorrect. – zerkms Nov 02 '14 at 22:55