返回递归函数的Javascript闭包

返回递归函数的Javascript闭包,javascript,function,recursion,closures,late-binding,Javascript,Function,Recursion,Closures,Late Binding,我不熟悉Javascript和函数范例。我真的很喜欢使用闭包将一点点状态安全地封装在私有范围中。这是一个令人耳目一新的变化,与爪哇的阶级崇拜歌舞不同 我编写以下代码的目的是将0-9打印到控制台。它是有效的,但我很惊讶它能起作用 我不明白next如何引用递归next()调用的返回的函数!它是否与Javascript的“后期绑定”属性有关 var next = (function() { // begin stateful wrapper function var current = -1

我不熟悉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()调用是如何引用的 返回的函数是什么

当您调用函数来构建定义
next
(在
}行中)的函数时;//立即调用包装器函数),您只返回一个函数(函数在被调用之前只是JavaScript中的另一种数据),该函数引用全局
next
变量,但尚未使用它。下一步(
next();
)开始该过程,到那时,内部
next
引用可以找到全局
next
定义

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

在这里访问
next
比较晚,因为函数不需要在定义时可用,而需要在调用时可用(虽然函数在定义内部函数时也知道变量
next
,但当时它的值是
undefined
;JavaScript也知道该变量,即使您的所有代码都在函数中,并且
var
设置在块的末尾)

(一个小提示(如果信息太多,可以忽略):这是良好的实践(对于“严格模式”来说是必要的)用
var
定义全局变量,比如
next
。JavaScript将变量引用视为全局变量,除非
var
在该范围内使用,但如上所述,即使所有代码都在函数中,并且
next
是局部变量,其
var
定义也允许在闭包中的任何位置发现该变量,甚至在嵌套函数中也发现了该变量(这与另一种蠕虫不同)

在哪里可以看到这里发生的事情的细节

您可能会发现这很有帮助:

更新

答复一项评论:

在JavaScript中

  • 如果一个函数变量(或任何类型的变量)是用
    var
    定义的,则在该范围内(包括在顶部全局范围内定义的情况)它被识别为
    未定义的
    (而不是类型错误),直到分配给它函数值(以便可以执行或传递)。同样,对于现有对象的赋值,例如
    window.myFunc=function(){};
  • 如果一个函数只是在没有
    var
    的情况下声明,比如
    function myName(){}
    ,那么它在声明之前或之后,在该范围内的任何地方都可以立即使用。与
    var
    函数声明一样,它可以类似地被视为数据,函数作为数据传递,例如回调函数
  • 如果函数变量被定义为变量,但在全局范围内的任何位置都没有使用该名称的
    var
    ,例如,
    myGlobal=function(){};
    ,则即使这样也不会产生错误(并将像上面的#1一样工作),除非有效,在这种情况下,它将产生错误

  • 可能您对立即调用的最外层函数感到困惑。这只用于保护变量范围内的当前函数。如果我们消除它,可能会更清楚

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

    但是由于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();
    
    var-next;
    (function(){//创建一个变量作用域,该变量作用域具有'current'和函数
    无功电流=-1;
    下一步=函数(){
    电流+=1;
    如果(电流<10){
    console.log(当前);
    next();//递归调用
    }否则{
    返回;
    }
    };
    }());
    next();
    
    下一步是由它执行的时间来定义的……是的,包装函数让我很困惑。你的重写澄清了这一点。在这个问题和这个注释之间,我读到了。我很确定我在把包装看作函数定义和函数表达式之间犹豫了。所以后期绑定根本没有关系?@kdbanman:我倾向于JavaScript中几乎所有的东西都被认为是后期绑定,但是没有,她在编写
    next
    变量的赋值时没有什么特别的地方。尽管我写了
    var next
    ,但我很确定我一直在想它是一个函数声明,而不是
    var
    。因此,编写嵌套的
    next()
    调用不是语法错误,因为在执行包装函数之前,变量
    next
    仍然存在,它只是
    未定义的
    。这是否正确?我在回答的末尾添加了一个更新,解决了可能出现的问题。您的描述是正确的,但除非“严格模式”应用时,即使没有
    var
    ,它也将被识别为全局(并且不会产生错误)。根据Douglas Crockford,如此轻松地创建全局的能力被列为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();
    
    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();