7
function A() {
     function B() {
          ...
     }        
     B();
}

Is function B created every time A is called or is there some caching on it. Is not making it local like :

function A() {
    B();
}
function B() {
    ...
}

A significant performance improvement?

Is it valid to do this a style choice? (B in this case is just a helper function for A.) or should the second be favoured for speed?

Should this style be used or avoided for readability?

Benchmark.

Seems like FF4 inlines B for the local case and removes the function call overhead.

What about other browsers?

Raynos
  • 156,883
  • 55
  • 337
  • 385
  • Declaring a function inside another is bad. In your first example B() should have been an expression. See here: http://stackoverflow.com/questions/1013385/what-is-the-difference-between-a-function-expression-vs-declaration-in-javascript – DanMan Mar 24 '11 at 18:06
  • 1
    It looks like your test case isn't correct; you aren't actually executing the functions, just declaring them. Checkout http://jsperf.com/inner-function-optimization. Chrome doesn't seem to optimize. I doubt any engines will. – Matt Mar 24 '11 at 18:38
  • @Matt Oh.. I forgot to call them. How stupid :( – Raynos Mar 24 '11 at 20:18
  • Hey, @Raynos. This is a good question. But if what you're looking to benchmark includes execution, would it make sense to edit the question to include a benchmark that reflects that? – s4y Mar 26 '11 at 19:42
  • @DanMan Why is a function declaration inside of a function bad? I have not heard that claim before. And the question and answers that you linked to do not seem to make that suggestion. – Jesse Hallett Apr 03 '11 at 21:36
  • @JesseHallett. It's not. He's wrong. – Raynos Apr 03 '11 at 21:59
  • @Jesse Hallett: On that page I've linked to you can find this link: http://kangax.github.com/nfe/ posted by Khon Lieu which explains it. Check the first green box. It's because of how interpreters work (first all function declarations, then all the other code). It should actually throw an error, but because of all the bad code out there browsers decided to recover from it. Just because it works doesn't mean it's right. – DanMan Apr 04 '11 at 17:09
  • 1
    @DanMan Yes that's correct. Function declarations inside blocks is disallowed. That's different from function declarations inside functions. This is because there is no block scope. There are indeed problems with browsers emulating block scope for function declaration and this is very bad. But this has nothing to do with function declaration inside functions. – Raynos Apr 04 '11 at 17:30
  • 1
    @Jesse Hallett: You're right. Looks like I didn't differentiate blocks from functions. Thanks for clearing that up. – DanMan Apr 04 '11 at 21:21

3 Answers3

4

Declaring an inner function in JS might have the purpose of being lexically bound to the outer function's local variables/arguments. Moving it out to be a top-level function defeats that purpose.

To answer the question: yes, the inner function is created every time, at least in theory, and this is how you should view it when writing the code, but a smart optimizer can still convert it to a top-level function, even if you have lexical dependencies. If it's a micro-optimisation, I wouldn't bother because having an inner function also serves the purpose of readability and declaring your intentions.

Erik Kaplun
  • 33,421
  • 12
  • 92
  • 102
0

Raynos, I looked at your jsperf tests, and it looks like you are testing the function declaration, not the function execution.

See the link below. Is that helpful?

Another benchmark

I would say that:

  1. In your sample code, B is created every time A is invoked. (In my sample linked to above, see the Outer Ordinary test.)

  2. Percentage-wise, the performance improvement is significant. But, if the real-world function runs in microseconds, you might not notice a difference.

  3. Another consideration is how important is it for B (the helper function) to be "private" (in other words, visible only inside of A). See the Outer Immediate function in my link for a middle-of-the-road option.

Aaron Kurtzhals
  • 1,997
  • 3
  • 14
  • 20
0

That's odd, because I would guess that re-declaring a function every time another is called would slow down execution time.

Does anyone have an answer to this?

The only solution I can come up with is that function C has to leave it's scope, move up to the global one, execute function D, then go back. Whereas function A stays within one scope through out execution. Any thoughts?

minond
  • 29
  • 3