我正在阅读答案的评论并看到了this comment:
[闭包]不会持久保存foo的状态,因为它创建了一个特殊的范围,包含(1)返回的函数和(2)返回时引用的所有外部变量 . 这个特殊范围称为闭包 .
好的,到目前为止一切顺利 . 现在这里是我不知道的有趣部分:
一个例子......如果你在foo中定义了另一个未在return函数中引用的var,它将不存在于闭包范围内 .
我想这是有道理的,但除了内存使用/性能之外还有什么影响呢?
Question - 如果范围中的所有变量都包含在闭包中,那么我可以做什么呢?我不能用当前模型做什么?
4 回答
我认为你太过于字面意思 . 评论只是说你不能在函数范围之外访问它(它不能公开访问),而不是它在函数中根本不可用 . 无论如何,返回的函数都可以访问所有外部函数范围 . 如果内部函数不提供访问它的方法,则您无法在外部函数外部访问该范围 .
例如,此表达式的计算结果为4:
http://jsfiddle.net/dmRcH/
所以尽管没有被直接引用,
x
仍然可用进一步研究
看来chrome和firefox至少会尝试优化这个,因为如果你没有提供任何方式来引用
x
变量,它就不会显示为在调试器中可用 . 在闭包内部使用断点运行此操作会显示x
在Chrome 26和Firefox 18上不可用 .http://jsfiddle.net/FgekX/1/
但这只是一个内存管理细节,而不是语言的相关属性 . 如果有任何可能的方法可以引用变量,那么它就会被传递,我怀疑其他浏览器可能不会以相同的方式对其进行优化 . 编码规范总是比实现更好 . 在这种情况下,虽然规则确实是: "if there's any possible way for you to access it, it will be available" . 而且, don't use eval because it really will keep your code from optimizing anything .
这不完全准确;变量是闭包范围的一部分,即使它不能直接在函数内部引用(通过查看函数代码) . 不同之处在于引擎如何优化未使用的变量 .
例如,当您使用DOM元素时,已知闭包范围中未使用的变量会导致内存泄漏(在某些引擎上) . 以这个经典的例子为例:
Source
在上面的代码中,内存被泄露(至少在IE和Mozilla中),因为
el
是单击处理函数的闭包范围的一部分,即使它被删除,因为它们的垃圾收集基于引用计数 .另一方面,Chrome使用different garbage collector:
这也称为世代或ephemeral garbage collector . 虽然更复杂,但这种类型的垃圾收集器可以更准确地确定是否使用变量 .
JavaScript没有固有的隐私感,因此我们使用函数范围(闭包)来模拟此功能 .
您引用的SO答案是模块模式的一个示例,Addy Osmani在Learning JavaScript Design Patterns中解释了重要性: