我正在做一个经过范围/闭包的课程,并简要提到垃圾收集。在课程期间提出了一个问题:
范围保持多久?答案是 - 直到 已经不再有任何参考。是的,所以我们基本上说了什么 是的,闭包有点像隐藏范围对象的引用。 所以,只要有一些功能仍然有一个关闭 范围,该范围将保持不变。但一旦关闭 消失,范围可以收集垃圾。 "
var sum = function sumHndlr(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) {
return x + y;
}
}
}
所以对我来说,对闭包的引用就是我们将函数赋值给sum
变量,但是它不会意味着它会永远存在,或者我不理解js在js中的执行方式关于编译器解析器等?
答案 0 :(得分:1)
非常简单,垃圾收集是Javascript解释器/虚拟机的后台进程,可自动释放程序不再需要的对象的内存。
例如,因为您将其视为事件侦听器:当您从某个事件调度程序中删除事件侦听器(通常是一个函数)时,程序的其他任何部分都可能没有对事件侦听器的引用。因此,垃圾收集器可以并且将(在某个未知时间)释放事件监听器所占用的内存。
由于闭包引用了一个scope对象,为了对一个闭包进行垃圾收集,它不仅需要不引用,还需要范围。
如果我修改你的例子:
/* 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]
)仍然引用引用{{}的范围1}}和x
因此,y
中的两个闭包都不能被垃圾收集器释放,直到程序引用sums
。
我希望这更加清晰,尽管这些示例当然与实际代码无关。实际上,只有在开发具有复杂闭包使用的长期程序(例如单页面应用程序或nodeJS服务器)时,才需要担心这一点。否则,闭包的内存使用不太可能成为问题。
这个SO问题提供了有关Javascript垃圾收集的更多详细信息:What is JavaScript garbage collection?