JavaScript闭包问题:为什么第二次调用outerFn会创建一个新的outerVar实例?
JavaScript Closure question: why is the second call to outerFn creating a new instance of outerVar?
我在理解闭包方面取得了进展,但我不明白下面的例子是如何创建闭包的。我将引用《学习jQuery》第392页中的一段话,以及作者对这个例子的看法。
作者说,因为"readyVar在函数调用之间持续存在",我们可以看到其中涉及到闭包。但是,对我来说,readyVar在调用innerFn之间持续存在只是因为匿名函数尚未完成执行。一旦匿名函数完成,就不会有对readyVar的引用,并且它将被垃圾收集。那么结束在哪里呢?在我的印象中,闭包涉及变量在定义变量的作用域之外的作用域中可引用。但是我在这里没有看到。
作者是说任何时候内部函数引用外部函数中定义的值,就会创建闭包吗?他不会是这个意思吧?
这条信息的其余部分引用了前面提到的那本书
$(document).ready(function() {
var readyVar = 0;
function innerFn() {
readyVar++;
$('#example-9').print('readyVar = ' + readyVar);
}
innerFn();
innerFn();
});
这看起来像我们前面的许多例子,除了在这种情况下,外部函数是传递给$(document).ready()的回调函数。由于innerFn()是在它内部定义的,并且引用回调函数范围内的readyVar,因此innerFn()及其环境创建了一个闭包。我们可以通过注意readyVar的值在函数调用之间持续存在来看到这一点:readyVar = 1readyVar = 2
在$(document).ready
函数的持续时间内,它的所有局部变量都是活动的,并保持它们的值,该函数中的任何代码或任何嵌入函数都可以引用它们。虽然可以将其描述为函数闭包,但这更像是局部变量在函数中的工作方式。
如果在$(document).ready
中,有一个嵌入函数在某处存储引用(如单击处理程序),那么将建立一个持久的函数闭包,并且readyVar
的值将与任何嵌入引用的持续时间一样长。它本质上是垃圾收集。只要函数循环外的某个东西持有对循环内某个东西的引用,循环就保持存活。当循环执行完成,并且循环外没有任何嵌入函数引用到循环内的东西时,循环被垃圾收集并消失。
因为没有嵌入函数引用在你现在拥有的,它将被垃圾收集(例如销毁和释放),当它完成执行。
现在,如果您修改它以添加像这样的单击处理程序,那么您现在就有了对$(document).ready
函数中具有单击处理程序函数的函数的持久引用。因为它仍然存在,即使在$(document).ready
循环完成执行之后,它也不会被垃圾收集,而是作为函数闭包存在。
$(document).ready(function() {
var readyVar = 0;
function innerFn() {
readyVar++;
$('#example-9').print('readyVar = ' + readyVar);
}
innerFn();
innerFn();
$("#content").click(function(){ // external reference to within this function
alert(readyVar);
});
});
我从你的问题中感觉到你混淆了局部变量和函数闭包。这两者是相关的,但不是同一件事。局部变量在函数的生命周期内总是可用的。函数的生命周期是指它正在执行的时间,除非对其中的闭包的引用导致它持续的时间超过了这个时间。
您可能会发现这很有帮助:http://blog.morrisjohns.com/javascript_closures_for_dummies.html
- 同一项怎么可能在一个实例中未定义,却在另一个实例上定义
- jQuery"焦点”;在一个实例中有效,但在其他实例中无效
- 当与另一个实例进行比较时,我的类实例如何隐式返回数字
- 为什么可以't我使用成员方法初始化一个实例
- 如何使用 JavaScript 正则表达式搜索除一个实例之外的所有内容
- 挖空视图模型函数仅影响最后一个实例
- 插件总是只得到最后一个实例,如何让它适用于多个元素
- arguments变量是的一个实例
- 使用javascript删除特定HTML实体(breadcrumb)的最后一个实例
- jquery获取类的下一个实例的值
- 如何使外部按钮只影响类的一个实例
- javascript中的Ruby插值在两个实例中的一个实例中不起作用
- 剑道网格:在Angular指令中获取一个实例
- 多个 xmlhttp 请求会导致除最后一个实例之外的所有实例的 readystate 都达不到 4
- Wordpress jQuery 脚本不会在具有 jQuery.noConflict 用法的一个实例上启动
- 如何将 url (http://example.com) 的一个实例限制为仅在客户端打开一次
- 在单个页面上使用此.js 2 次时,它仅适用于一个实例
- 查找给定工作日的下一个实例(即.星期一)与时刻.js
- 谷歌地图将边界限制在世界的一个实例中
- CKEditor 一个实例用于多个 ID