16

If i have a function like this

function do(callback) {
 //do stuff
 callback();
}

and then I pass in an anonymous function:

do(function() { //do something else });

does that anonymous function ever get collected during the lifespan of the page? If not, how can i make it available for GC?

do I have to do this?

var h = function() { //do something };
do(h);
delete h;

Do I even have to worry about this? I am building a web app that has a long lifespan, makes a lot of ajax calls keeps objects for a while and doesn't really require a page refresh to navigate thru. So I'm trying to figure out if I might fall into a memory leak monster.

asked Jun 9, 2011 at 17:41
1

2 Answers 2

13

The only reference to the anonymous function is the function argument, and that disappears when the function finishes, so your callback will be available for garbage collection after that. Except when something else gets a reference to it, which can happen easily with closures:

function doo(callback) {
 $.get(url, function() {
 // callback is visible here!
 });
 callback();
}
doo(function() { /* do something else */ });

callback (along with the whole scope created by calling doo) must stay in the memory, because the inner function can reference it through the closure; it can only be garbage collected when the inner function is garbage collected, and since that function is a property of the jqXHR object, that object must be garbage collected before that, and who knows when that will happen...

Update You can avoid unnecessary closures by not defining your functions inside other functions:

var func = function() {
 // callback is not visible here
}
function doo(callback) {
 $.get(url, func);
 callback();
}
doo(function() { /* do something else */ });
answered Jun 9, 2011 at 19:10
Sign up to request clarification or add additional context in comments.

6 Comments

if i would do this in the doo function var var g = $; g.get... would that make callback collectable? or what could I do make your example collectable?
@Jose: referring to $ by another name does not do anything useful. I updated my answer to show how closures can be avoided. Of course, if you can just always reuse the same arguments in your calls to doo instead of creating an anonymous function every time, that is a simpler way to solve the problem.
I think you mean "var func = function()..." not "var fun" ... either that or $.get(url, func) should get updated.
@Crashalot: fixed, thanks. Looking back, using a deferred would have been more elegant though: function doo() { return $.get(url).then(function () {/*...*/}); }; doo().then(function() {/* do something else */});
@losnir, that depends on the JS engine. Some constructs make it impossible to tell what variables will be used (e.g. jsfiddle.net/x8xL8dwq ) - modern browsers evaluate code containing such constructs differently, older ones don't.
|
2

Watch out for circular references, otherwise the GC for the browser will clean those up. Closures make it really easy to create a circular reference, and that might be trapped in memory even if you browse away from the page that created it. So, web applications that stay on-screen for long periods of time are especially vulnerable.

Check out the section "Memory leaks" here: https://developer.mozilla.org/en/A_re-introduction_to_JavaScript.

I've designed quite a few static-page web applications. I've found that even when you don't have to clean up objects and event handlers (ie you're sure there is no circular reference), it can't hurt. It usually only adds a couple of extra lines of code, and it keeps memory use and efficiency at the forefront of your mind as you write your code. This is something of a shift for web developers because we usually don't have to think about this kind of thing very much when creating a website.

answered Jun 9, 2011 at 17:49

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.