34

At some point in the past, I read something that gave me the idea that anonymous functions in JavaScript can use up a surprising amount of memory (because they carry the entire current scope around with them), whereas named (static?) functions don’t have this issue.

I can’t remember where I read this, so I can’t go back and re-read it and figure this out for myself.

I’ve got two questions:

  1. Are there situations where anonymous functions can use enough memory for it to be worth caring about? (If so, do you have an example?)
  2. Are there any other drawbacks to anonymous functions (as opposed to named/static functions)?
7
  • Excellent question. I've used up my votes for the day - can someone else +1 for me? Commented Jul 14, 2011 at 18:49
  • @Michael Already did. Great question. Commented Jul 14, 2011 at 18:49
  • There have been similar question on SO about the implementation of closures, but I have yet to see one with a satisfactory answer. That is, are modern JavaScript engines smart enough to only keep around objects in the [[scope]] which can be accessed? Obviously this optimization is not practical to apply in presence of eval, etc... Commented Jul 14, 2011 at 18:50
  • 1
    F—ing hell, 8 upvotes in four minutes? I assumed I was being dumb. Commented Jul 14, 2011 at 18:52
  • 3
    Actually, every function, whether anonymous or not, declaration or expression, has access to each higher scope. So you could generalize the question and ask whether functions in JavaScript have a memory issue or maybe better: What are the memory implications if functions are passed out of the scope they are defined in (which is then about closures I guess). Commented Jul 14, 2011 at 18:54

3 Answers 3

8

All JavaScript functions will behave in the same manner in that they inherit the variable environments in entire scope chain leading up to, and including, themselves. This is equally true for both anonymous and named functions.

This chain of references to the outer environments stays with each function, even if the function is passed into an entirely different scope.

Traditionally, this would mean that all variables in any given chain have a reference retained to them as long as the inner closure continues to exist. Although in modern browsers that compile the code, it is likely that there will be an analysis of which variables are actually referenced, and only those will be retained, allowing others that are no longer referenced to be garbage collected.

However, there are other situations where an anonymous function is wasteful.

Here's a common bit of code:

for( var i = 0; i < 100; i++ ) {
    (function( j ) {
        setTimeout( function() { console.log( j ); }, 1000 );
    })( i );
}

This is a situation where an anonymous function is a bit more wasteful than a named function because you're recreating an identical function 100 times during the loop when you could just reuse a named one.

function setConsole( j ) {
    setTimeout( function() { console.log( j ); }, 1000 );
}

for( var i = 0; i < 100; i++ ) {
    setConsole( i );
}

This has the exact same closure overhead, but is more efficient because you've only constructed one function to create each new variable environment.

http://jsperf.com/immediate-vs-named (Thanks to @Felix Kling for the jsPerf.)

So with respect to the closure in particular, yes there's overhead as long as you maintain the closure by some permanent reference. I'd say that it is good to avoid this if possible but not to be obsessive about it. Sometimes a new variable environment added to the scope chain is simply the best solution.


EDIT: Here's an article from Google. Specifically, see Avoiding pitfalls with closures. for information on the performance impact of extending the scope chain, and for a claim that anonymous functions are “slower” than named functions.

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

4 Comments

Moderator Note Comments under this answer were removed because they degenerated into more noise than signal. Please keep comments constructive, professional and most of all on topic.
Thanks to @Tim Post for the removal. The result of the relevant discussion with OP, as well as the performance test provided by @Felix Kling has been added to the answer.
@user113716 Can you explain this line ` more efficient because you've only constructed one function to create each new variable environment`?
@user113716 Suppose there was a variable a outside of setConsole used by function passed to setTimeout, shouldn't the memory only matter then, and not in this case? I mean how is one case more efficient than other in current setup.
3

I think what you probably read about was the IE closure memory leak problem.

Look at this article on the issue.

Basically, on older versions of IE, the garbage collector could not handle circular references involving DOM objects. Since closures are very conducive to such circular references, they could easily lead to annoying memory leaks in IE.

1 Comment

Yeah, I’m not sure it was that — I do remember the IE circular references thing, and that it had to do with closures (I could never quite get the full details of it to stick in my head), but I think the thing I read was a more general point about anonymous functions.
0

This is true, due to closures that are created. as a general rule the biggest issue with the practice is performance concerns with IE (especially older versions of IE), which has a terrible track record of dealing with these properly.

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.