这既是一个词汇范围界定的例子,也是一个确认我自己理解的问题。首先,考虑以下示例:
Html:
<div id="testtxt"></div>联署材料:
function fnTest(currentIdx, endIdx) {
$('#testtxt').html($('#testtxt').html() + 'Function Called ' + currentIdx + '<br />');
if (currentIdx < endIdx) {
setTimeout(function(){
fnTest(currentIdx + 1, endIdx);
}, 100);
}
}
fnTest(1, 10);
fnTest(11, 20);输出:
Function Called 1
Function Called 11
Function Called 2
Function Called 12
Function Called 3
Function Called 13
Function Called 4
Function Called 14
Function Called 5
Function Called 15
Function Called 6
Function Called 16
Function Called 7
Function Called 17
Function Called 8
Function Called 18
Function Called 9
Function Called 19
Function Called 10
Function Called 20当我第一次运行这个示例时,我担心fnTest会有一个单一的全局闭包,因此currentIdx和endIdx将被fnTest的两个调用所设置和访问。然而,情况并非如此。
请告诉我以下是否是一个很好的解释方法:
每次对fnTest的调用都会创建一个唯一的对象,在该对象中,变量currentIdx和endIdx存储在该调用的生存期内,以及该调用中的所有子例程(这称为闭包)。setTimeout调用从匿名函数创建一个新对象,匿名函数可以访问fnTest闭包,因此可以引用currentIdx和endIdx,此对象/函数将在延迟100 has后执行。在执行时,匿名函数本身将通过调用fnTest创建一个新的fnTest闭包。此时,可以释放匿名函数引用的原始fnTest闭包。
如有必要,请改正我的技术术语。
发布于 2015-12-09 19:07:53
基本上对,有几点:
每次对fnTest的调用都会创建一个唯一的对象,在该对象中,变量currentIdx和endIdx存储在该调用的生存期内.
该对象的生命周期,正如Felix所说的,它被称为环境。这个生命周期就像所有其他对象的生命一样:只要某物仍有引用。特别是,在fnTest返回之后(在本例中),它继续进行。
唯一能够引用这些环境对象的东西是在这些对象中创建的函数,称为闭包(它们“关闭”于环境)。
...and调用中的所有子例程(这称为闭包)
这些函数称为闭包,而不是环境。
setTimeout调用从匿名函数创建一个新对象。
不,您的代码正在创建一个匿名函数,并将对该函数的引用传递给setTimeout。
...which可以访问fnTest闭包,因此可以引用currentIdx和endIdx。
它可以访问创建它的环境。
此对象/函数将在延迟100后执行。在执行时,匿名函数本身将通过调用fnTest创建一个新的fnTest闭包。
是的,它通过调用fnTest创建了一个新的环境。
此时,可以释放匿名函数引用的原始fnTest闭包。
由于计时器机制已经发布了对匿名函数的引用,因此不再引用匿名函数,而且它可以被垃圾收集。因为它是从最初对fnTest的调用中引用环境的唯一方法,所以这个环境也可以被垃圾收集。
我们正在做一些挥手在上面的细节,但重要的概念是存在和正确的。
https://stackoverflow.com/questions/34186825
复制相似问题