Reputation: 7739
I am doing a course which is going through scope/closures and briefly mentions garbage collection. During the course a question is posed:
How long does the scope stay around? And the answer was—until there's no longer any references to it. Yep, so what we basically said was, a closure is kind of like a reference to a hidden scope object. So as long as there's some function that still has a closure over the scope, that scope's going to stay around. But as soon as that closure goes away, scope can get garbage collected. "
var sum = function sumHndlr(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) {
return x + y;
}
}
}
So to me, the reference to the closure is when we assigned the function to the sum
variable, but won't that mean it lasts forever or am I not understanding the way the js will execute in regards to the compiler parser etc.?
Upvotes: 4
Views: 1961
Reputation: 4175
Very briefly, garbage collection is a background process of the Javascript interpreter / virtual machine that automatically frees the memory of objects no longer needed by your program.
For example, since you think of it for event listeners: when you remove an event listener (a function usually) from some event dispatcher, it is likely that no other part of the program will have a reference to the event listener. Therefore, the garbage collector can and will (at some unknown time) free the memory that was taken by the event listener.
Since a closure references a scope object, in order to garbage-collect a closure it needs not only be unreferenced, but also the scope.
If I modify a bit your example:
/* some stuff ... */
function add10(a) {
var adder = function (x) {
return function(y) {
return x + y;
}
}
var sum = adder(10); //creates a closure
return sum(a);
}
var thirty = add10(20);
/* Some more stuff ... */
After add10
is called, even though the program continues to execute some more stuff, the garbage collector can free the memory associated to the closure sum
, because it is no longer referenced, nor is the scope associated to it.
Whereas in this example:
/* some stuff ... */
function add10AndGet20Adder(a) {
var adders = function (x, y) {
return [function(z) {
return x + z;
}, function(z) {
return y + z;
}]
}
var sums = adders(10, 20); //creates a closure
return [sums[0](a), sums[1]];
}
var result = add10AndGet20Adder(50);
var sixty = result[0];
var add20 = result[1];
/* Some more stuff ... */
When executing some more stuff, sums[0]
is no longer referenced, BUT add20
(sums[1]
) still has a reference to the scope that references x
andy
, therefore none of the two closures in sums
can be freed by the garbage collector, until add20
is referenced by the program.
I hope this makes it clearer, even though the examples are of course nowhere close to real code. In practice, you need to worry about this only if you develop a long-lived program (such as a single page application or nodeJS server) with complicated usage of closures. Otherwise, the memory usage of the closures is unlikely to be a problem.
This SO question gives more details about Javascript garbage collection: What is JavaScript garbage collection?
Upvotes: 3