Reputation: 717
I've been uncertain about the rules of JS garbage collection around a closure for a while, so I figure I might as well ask... Here's a good example that I'm curious about involving jQuery's $.each
method:
storeSelection: function() {
var enabledIds = {};
$.each(this.nodes, function(index, node) {
if (node.enabled) {
enabledIds[ node.id ] = true;
}
});
this.selection = enabledIds;
}
The above snippit is, of course, part of an object literal. So, I've created a new object at the top of the outer function which will store the IDs of enabled items within an array. Using jQuery's .each()
method, I'm looping through the array of items and logging enabled IDs. Finally, I store the selection as a member of the parent object.
My question involves that inner function which references the enabledIds
object from the outer scope. Since enabledIds
will be sticking around, does that prevent the inner function from being collected? I would assume not, because it's just a variable that gets cleared at the end of the inner function, right? To become a leak, I assume the inner function would need to make a hard reference to the outer object, as in:
$.each(this.nodes, function(index, node) {
this.badIdea = enabledIds;
if (node.enabled) {
enabledIds[ node.id ] = true;
}
});
However... I'm always foggy on this rule. Any help clearing up this confusion would be appreciated!
Upvotes: 2
Views: 86
Reputation: 12197
You're right, the variables from the inner function (index
, node
) will be garbage-collected, because they can't be accessed anymore.
In this example, can you access bigstr
?
a = function() {
var bigstr = new Array(1000000).join('x');
return function() { return bigstr; };
}();
Yes, you can: a()
, so it's not collected. What about this example:
a = function() {
var bigstr = new Array(1000000).join('x');
return function(n) { return eval(n); };
}();
Again, you can: a('bigstr')
.
But what about this one:
a = function() {
var smallstr = 'x';
var bigstr = new Array(1000000).join('x');
return function(n) { return smallstr; };
}();
You can't access it anymore, and it's a candidate for garbage collection.
Upvotes: 1
Reputation: 239440
No, even your second example wouldn't be enough to cause a leak. badIdea
is attached to the individual nodes, and the $.each
block would exit and be garbage collected. All modern browsers use a "mark and sweep" algorithm for javascript garbage collection, which follows associations parent to child and collects any "unreachables", i.e. anything that can't be accessed by one of these trees.
Upvotes: 3