【问题标题】:Lexical Scope/Closures and Global Function Recursion词法作用域/闭包和全局函数递归
【发布时间】:2015-12-09 18:57:14
【问题描述】:

这既是一个词法作用域的例子,也是一个确认我自己理解的问题。首先,考虑以下示例:

HTML:

<div id="testtxt"></div>

JS:

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 毫秒延迟后执行。在执行时,匿名函数本身将通过调用 fnTest 创建一个新的 fnTest 闭包。此时,匿名函数引用的原始 fnTest 闭包可能会被处理掉。

请在必要时更正我的技术术语。

【问题讨论】:

  • “每次调用 fnTest 都会创建一个唯一的对象,其中存储了变量 currentIdx 和 endIdx”。这个“对象”被称为环境。每当您调用函数时,都会创建一个新环境。

标签: javascript closures lexical-scope


【解决方案1】:

基本正确,有几点:

对 fnTest 的每次调用都会创建一个唯一的对象,变量 currentIdx 和 endIdx 在该调用的生命周期内存储在其中...

对于该对象的生命周期,正如 Felix 所说,它被称为 环境。该生命周期就像所有其他对象的生命周期:只要某些东西仍然具有对它的引用。特别是,它会在fnTest 返回之后继续(在这种情况下)。

唯一可以引用这些环境对象的是在其中创建的函数,称为闭包(它们“关闭”环境)。

...以及该调用中的所有子例程(这称为闭包)

函数称为闭包,而不是环境。

setTimeout 调用从匿名函数创建一个新对象

不,您的代码正在创建一个匿名函数并将对该函数的引用传递给setTimeout

...可以访问 fnTest 闭包,因此可以引用 currentIdx 和 endIdx

它可以访问创建它的环境

此对象/函数将在 100 毫秒延迟后执行。在执行时,匿名函数本身会通过调用 fnTest 创建一个新的 fnTest 闭包。

它通过调用fnTest创建一个新环境,是的。

此时匿名函数引用的原始 fnTest 闭包可能会被处理掉。

由于定时器机制已经释放了它对匿名函数的引用,所以不再引用匿名函数,它可以被垃圾回收。由于它是从最初调用 fnTest 时唯一引用环境的东西,因此该环境也可以被垃圾收集。

我们正在对上述细节进行一点,但重要的概念是存在且正确的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-20
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2011-05-02
    • 2021-03-24
    • 2016-08-25
    • 1970-01-01
    相关资源
    最近更新 更多