Javascript闭包返回一个递归函数

时间:2014-03-01 02:51:01

标签: javascript function recursion closures late-binding

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

我编写了以下代码,打算将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

2 个答案:

答案 0 :(得分:4)

也许你对被立即调用的最外层函数感到困惑。这仅用于保护变量范围中的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变量。


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


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

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();

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

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

{{1}}

答案 1 :(得分:1)

  

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

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

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

next的访问是迟到的,因为函数不需要在定义时可用,而是在调用时可用(尽管函数已知变量next在定义内部函数的时间,但是当时它的值是undefined;即使您的所有代码都在函数内并且var已设置,该变量也将为JavaScript所知在块的末尾)。

(一个小注释(如果信息太多,你可以忽略):对你来说nextvar这样的全局变量是很好的做法(对于“严格模式”来说是必要的)已经完成.JavaScript会将变量引用视为全局变量,除非在该范围内使用var,但正如所提到的,即使你的所有代码都在函数内部并且next是一个局部变量,它的定义也是如此with var允许在闭包内的任何地方发现该变量,即使在嵌套函数中也是如此(与this不同,这是另一种蠕虫)。)

  

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

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

<强>更新

回复评论:

在JavaScript中......

  1. 如果使用var定义函数变量(或任何类型的变量),则在该范围内将其识别为undefined(而不是类型错误)(包括定义它的情况)在顶部,全局范围内),直到进行赋值以赋予它函数值(因此可以执行或传递)。与现有对象(例如window.myFunc = function () {};
  2. )的分配相同
  3. 如果声明的函数没有像var这样的function myName () {},则在声明之前或之后,该范围内的所有函数都可立即使用。与var函数声明一样,它可以类似地被视为数据,函数作为数据传递,例如,用于回调。
  4. 如果函数变量被定义为一个变量,但在全局范围内没有var存在该名称,例如myGlobal = function () {};,即使这样也不会产生错误(并且会像除非"strict mode"生效,否则它将产生错误。