返回递归函数的Javascript闭包
我不熟悉Javascript和函数范例。我真的很喜欢使用闭包将一点点状态安全地封装在私有范围中。这是一个令人耳目一新的变化,与爪哇的阶级崇拜歌舞不同 我编写以下代码的目的是将0-9打印到控制台。它是有效的,但我很惊讶它能起作用 我不明白返回递归函数的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
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();