繁体   English   中英

Javascript闭包返回一个递归函数

[英]Javascript closure returning a recursive function

我是Javascript和功能范例的新手。 我真的很喜欢使用闭包来保持一小部分状态在私人范围内安全地包裹起来。 从爪哇的阶级崇拜的歌舞中,这是一个令人耳目一新的变化。

我编写了以下代码,打算将0-9打印到控制台。 它有效,但我很惊讶它确实如此。

我不明白next如何引用递归next()调用的返回函数! 它与Javascript的“后期绑定”属性有关吗?

var next = (function() {  // begin stateful wrapper function
    var current = -1;

    return function() {   // begin returned function
        current += 1;
        if (current < 10) {
            console.log(current);

            next();       // recursive call 
        } else {
            return;
        }
    };    // end returned function

})();     // immediately call wrapper function

next();   // call returned function to generate output
  • 在执行期间,递归next()调用如何引用返回的函数?

  • 哪里可以读到有关这里发生的事情的详细信息?

(输出:)

0
1
2
3
4
5
6
7
8
9

也许你对被立即调用的最外层函数感到困惑。 这仅用于保护可变范围内的current 如果我们消除它,它可能更清楚。

var current = -1;
var next = function() {// This is what would have been returned in the original
    current += 1;
    if (current < 10) {
        console.log(current);

        next();       // recursive call 
    } else {
        return;
    }
};

next();

现在您与原始代码相同,只是current不在其自己的范围内。 如您所见,该函数只是分配给next变量。


这正是原始版本中发生的事情,除了原始外部函数存在并立即被调用。 该外部函数是一次性函数,虽然其return值为,但未分配给next


JavaScript没有块范围(但是),但如果确实如此,请将其视为与此类似:

var next;

{ // Create a (fictional) variable scope that has `current` and the function

    var current = -1;

    next = function() {
        current += 1;
        if (current < 10) {
            console.log(current);

            next();       // recursive call 
        } else {
            return;
        }
    };

}

next();

但由于JS没有块范围,只有函数范围,我们需要用函数来模拟它。

我们可以稍微调整原件以使其看起来相似。

var next;

(function() { // Create a variable scope that has `current` and the function

    var current = -1;

    next = function() {
        current += 1;
        if (current < 10) {
            console.log(current);

            next();       // recursive call 
        } else {
            return;
        }
    };

}());

next();

在执行期间,递归next()调用如何引用返回的函数?

当你调用函数来构建next定义的函数时(在带有})(); // immediately call wrapper function的行中})(); // immediately call wrapper function })(); // immediately call wrapper function ),你只返回一个函数(函数只是JavaScript中的另一种数据,直到被调用),它引用了全局的next变量,还没有使用它。 下一步( next(); )启动该过程,到那时,内部next引用可以找到全局next定义。

AFAIU,“后期绑定”的术语往往与属性的动态价值有关, this是一个特别重要的。

对于next访问是在这里,因为函数不需要在定义时可用,而是在调用时(虽然变量next在函数定义时已经为内部函数所知,但是它的值在那时是undefined ;即使所有代码都在函数内部并且var在块的末尾设置,该变量也将为JavaScript所知。

(一个小注释(如果信息太多,你可以忽略它):像你所做的那样定义全局像next var这是一个很好的做法(对于“严格模式”是必要的).JavaScript将变量引用视为全局变量,除非var在该范围内使用,但如上所述,即使您的所有代码都在函数内部并且next是局部变量,其使用var定义也允许在闭包内的任何位置发现该变量,即使在嵌套函数中也是如此(与this是另一种蠕虫病毒。)

哪里可以读到有关这里发生的事情的详细信息?

您可能会发现这有用: https//developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

UPDATE

在回复评论时:

在JavaScript中......

  1. 如果使用var定义函数变量(或任何类型的变量),则在该范围内将其识别为undefined (不是类型错误)(包括在顶部全局范围中定义的情况),直到赋值使它具有函数值(因此可以执行或传递)。 同样,对现有对象的赋值,例如window.myFunc = function () {};
  2. 如果声明的函数没有像function myName () {}那样的var ,则在声明之前或之后,该function myName () {}都可以立即使用。 var函数声明一样,它可以类似地被视为数据,函数作为数据传递,例如,用于回调。
  3. 如果函数变量被定义为变量,但在全局范围内没有任何带有该名称的var ,例如, myGlobal = function () {}; ,即使这不会产生错误(并且将像上面的#1一样工作),除非“严格模式”生效,在这种情况下它将产生错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM