Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/475.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在宿主函数返回后的事件中可用的JavaScript局部范围变量。为什么?_Javascript_Variables_Scope_Garbage Collection - Fatal编程技术网

在宿主函数返回后的事件中可用的JavaScript局部范围变量。为什么?

在宿主函数返回后的事件中可用的JavaScript局部范围变量。为什么?,javascript,variables,scope,garbage-collection,Javascript,Variables,Scope,Garbage Collection,所以。。。我来自C++背景,我不了解JS的一些东西。例如: function a() { var x = 0; // Local variable $(document).on('mousedown', function(){console.log('down: ', x++);}); $(document).on('mouseup', function(){console.log('up: ', x++);}); setInterval(function(){cons

所以。。。我来自C++背景,我不了解JS的一些东西。例如:

function a()
{
   var x = 0; // Local variable

   $(document).on('mousedown', function(){console.log('down: ', x++);});
   $(document).on('mouseup', function(){console.log('up: ', x++);});
   setInterval(function(){console.log('interval: ', x++);}, 1000);

   //W3schools: 'Local variables are deleted when the function is completed.'
}
a();

为什么控制台输出看起来像这样?(随机点击时)


我希望它是'undefined's或NaN或nulls,因为x应该在作用域的末尾被删除,但似乎所有三个回调都引用它,永远都很好。。。为什么?这是一个新的行为还是从旧的JS版本开始就这样工作?我找不到答案。

函数可以访问x,因为您在可访问的范围内给了它们该变量。它是累积的,因为在javascript中,您不提供实际值,只提供对它的引用,所以所有回调仍然引用a()函数中的x。而且因为它仍然被引用,javascript的垃圾收集器不会删除它,因为它认为它仍然在使用中(因为回调函数每次调用都使用它来增加它)。

W3schools的注释不完整。大多数情况下,当函数完成时(不一定是立即完成,但在下次运行垃圾收集时),变量确实会被清除。但这只是因为大多数时候没有更多的引用这些变量

但是,由于javascript支持函数作为第一类对象,因此它也支持闭包。当你有这样一行:

$(document).on('mousedown', function(){console.log('down: ', x++);});
…您正在创建一个闭包。这个闭包是新函数,加上定义它的词汇环境。它引用了
x
,因此即使
a
完成解析,
x
也不会被垃圾收集。稍后调用该函数时,它仍然可以很好地访问闭包变量


x
仍然可能被垃圾收集,但前提是引用它的所有闭包也被垃圾收集。在本例中,您可以通过注销mouseup和mousedown事件并取消间隔来实现这一点。

这就是闭包在javascript中的工作方式。这里有很多关于闭包的答案。为了添加到@Andrey comment中,在中有一个很好的解释,并提供了一个类似的示例。基本上,三个内部匿名函数的实例在它们的词法环境中保持对变量
x
的引用,因此变量
x
不能被垃圾收集。
$(document).on('mousedown', function(){console.log('down: ', x++);});