我正在上一门类(class),该类(class)介绍范围/闭包并简要提及垃圾收集。在类(class)中提出一个问题:
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;
}
}
}
所以对我来说,闭包的引用是当我们将函数分配给 sum
变量时,但这并不意味着它会永远持续下去,或者我不理解 js 的执行方式关于编译器解析器等?
最佳答案
简而言之,垃圾回收是 Javascript 解释器/虚拟机的后台进程,它会自动释放程序不再需要的对象的内存。
例如,由于您将其视为事件监听器:当您从某个事件派发器中删除事件监听器(通常是一个函数)时,程序的其他部分很可能不会引用该事件监听器。因此,垃圾收集器可以并将(在某个未知时间)释放事件监听器占用的内存。
由于闭包引用了作用域对象,为了对闭包进行垃圾回收,它不仅需要未被引用,还需要作用域。
如果我稍微修改一下你的例子:
/* 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 ... */
调用 add10
后,即使程序继续执行更多的东西,垃圾收集器也可以释放与闭包 sum
关联的内存,因为它不是不再被引用,也不是 与之关联的范围。
而在这个例子中:
/* 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 ... */
当执行更多东西时,不再引用 sums[0]
,但是 add20
(sums[1]
) 仍然有对引用 x
和 y
的作用域的引用,因此 sums
中的两个闭包都不能被释放垃圾收集器,直到 add20
被程序引用。
我希望这能让它更清楚,尽管这些示例当然与真实代码相去甚远。实际上,只有当你开发一个长期使用闭包的程序(如单页应用程序或 nodeJS 服务器)时,你才需要担心这一点。否则,闭包的内存使用不太可能成为问题。
这个 SO 问题提供了有关 Javascript 垃圾收集的更多详细信息:What is JavaScript garbage collection?
关于javascript - 这个作用域/闭包什么时候在 javaScript 中被垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37377653/