【问题标题】:Function closure and garbage collection函数闭包和垃圾回收
【发布时间】:2016-09-19 10:38:23
【问题描述】:

当涉及到函数闭包时,我很难理解垃圾收集是如何发生的。例如下面的 JS 代码使用闭包实现了一个加法器函数:

function adder() {
        var sum = 0
        return function(x) {
                sum += x
                return sum
        }
}

function abc() {
        var pos = adder()
        for (i = 0; i < 10; i++) {
                console.log(pos(i))
        }
}

abc()

输出:

0
1
3
6
10
15
21
28
36
45

每次调用pos 函数时,参数x 会添加到sum 并返回累积和。我不明白的是,为什么sum 的值保留在函数adder 中?不应该在内部函数返回时(即pos 返回时)立即将 sum 的值收集起来。

相反,每次使用新值x 调用pos 时,上一次调用的总和都会以某种方式保留在内存中。导致这种情况发生的幕后情况是什么?

【问题讨论】:

  • 函数引用sum,并且仍然存在对函数本身的实时引用,这意味着闭包不会被垃圾收集。这就是闭包的全部意义所在。
  • adder 被调用一次,其中var sum = 0 将被定义一次;然后sum 是从adder 返回的匿名函数的本地; var sum = 0 未设置第二次
  • @Pointy:但是当引用sum的内部函数返回时,sum不会被垃圾回收吗?
  • 不,因为变量 pos 仍然是对该返回的内部函数的活动引用。

标签: javascript node.js garbage-collection closures


【解决方案1】:

这背后的魔力是闭包:-)

每次调用函数时,都会为函数内部发生的所有事情留出一些内存(称为闭包)(大括号 { ... } 之间)。此外,函数可以访问在其外部定义的所有内容。

因此,当您在第 10 行调用函数 adder() 时,它会创建此闭包并将 sum 存储在其中。然后,adder() 返回一个函数。对于这个内部函数,sum 是全局的,因此它可以在其主体内部访问和修改它,并且即使内部函数终止,值(存储在函数周围的闭包中)仍然存在。更重要的是,只要在程序中有对内部函数的引用,闭包就不会被垃圾回收,因为 JavaScript 知道内部函数可能与闭包交互。

总而言之,闭包对内部函数是全局的,但对外部世界是不可见的,这使得它们对于在浏览器中封装 JavaScript 应用程序的某些部分非常有用。在 node.js 中,这方面并不那么重要,因为模块概念已经进行了封装。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 2015-06-10
    • 2015-11-13
    • 2011-09-11
    • 1970-01-01
    相关资源
    最近更新 更多