0

Given the following two:

Scenario 1

function inner() {
  // a bunch of code that does stuff
}
function outer() {
  inner();
}
for(var i = 0; i < 10000; i++) {
  outer();
}

Scenario 2

function outer() {
  function inner() {
    // a bunch of code that does stuff
  }
  inner();
}
for(var i = 0; i < 10000; i++) {
  outer();
}

Behavior is identical in both cases, no doubt. But what's the difference under the hood? How much extra work, if any, is the interpreter doing in scenario 2? Is the memory affected. Or, say, if the body of inner() gets longer, would that increase the effect on performance?

Please don't bother asking "why would you want to do that", because my question is not about a practical issue. Just trying to get a deeper understanding of how JS function are parsed and represented. Thanks!

4
  • Have a look at this - jsperf.com/moretest Commented Nov 8, 2012 at 0:14
  • What you are trying to do in the second scenario is called Closure. You can use it for different things: - as a function factory - as a private method which can be called only from the outer function Commented Nov 8, 2012 at 0:14
  • 1
    While true (as far as it goes, there are a lot of other uses for closures, and outer is as much a closure as inner is), this is not an answer to what the OP asked. Commented Nov 8, 2012 at 0:17
  • Thanks for setting that up. I modified and added more tests. The results indicate that there is a cost to declaring a function repeatedly. And the 3 major browsers seem to agree. Commented Nov 8, 2012 at 6:25

2 Answers 2

1

But what's the difference under the hood? How much extra work, if any, is the interpreter doing in scenario 2?

It depends entirely on the JavaScript engine. (I don't call them "interpreters" any more, because so many of them actually compile on the fly.)

In theory, the engine might re-interpret/re-compile inner upon every entry into outer. Or at least, allocate a new inner for every call to outer.

The more likely scenario, with modern engines, is the code for inner is only compiled once, and reused, and a new function object is created for each call to outer which reuses that code with different execution context. The impact of this is negligible (consider how often you write {} in your JavaScript functions without worrying about the impact of creating an object). Certainly that's what V8 (the engine in Chrome) does in most situations, and almost certainly what most modern engines do.

Sign up to request clarification or add additional context in comments.

4 Comments

Since inner doesn't reference any variables in outer, no closure is needed, so couldn't a good compiler reuse the same function object every time? The only difference between the two scenarios could be whether inner is added to the global namespace.
@T.J. Crowder, that sounds plausible to me – and it's how I was hoping it'd be – but test results seem to indicate that there's a significant cost to redefining the function.
@meetamit: I didn't say there wasn't any cost. :-) But don't put too much faith in synthetic tests like that one. The test functions are unrealistic, they do nearly nothing. Any decent engine will inline them, and it may be that adding the nested function declaration prevents the inlining. Real code will actually do something in the function which may, itself, prevent the inlining. Even if not inlined, you're comparing the cost of basically the cheapest function call to one with a tiny bit more overhead, and seeing a tiny (in absolute terms) impact.
@T.J.Crowder Yeah, I buy these arguments. Thanks.
1

There are many engines: http://en.wikipedia.org/wiki/List_of_ECMAScript_engines

Some of them are JIT compiling therefore are faster than the others that interpret at runtime. The performance degradation is negligible for JIT compilers (compile inner once and reuse) but apparent for interpreters (interpret inner many times). More apparent when inner body grows.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.