递归调用javascript函数 [英] Calling a javascript function recursively
问题描述
我可以像这样在变量中创建递归函数:
I can create a recursive function in a variable like so:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
这样,functionHolder(3);
将输出 3
2
1
0代码>.假设我做了以下事情:
With this, functionHolder(3);
would output 3
2
1
0
. Let's say I did the following:
var copyFunction = functionHolder;
copyFunction(3);
将输出 3
2
1
0
为以上.如果我将 functionHolder
更改如下:
copyFunction(3);
would output 3
2
1
0
as above. If I then changed functionHolder
as follows:
functionHolder = function(whatever) {
output("Stop counting!");
然后 functionHolder(3);
会按预期给出 停止计数!
.
Then functionHolder(3);
would give Stop counting!
, as expected.
copyFunction(3);
现在给出 3
停止计数!
因为它指的是 functionHolder
,而不是函数(它本身指向).在某些情况下这可能是可取的,但有没有办法编写函数,使其调用自身而不是保存它的变量?
copyFunction(3);
now gives 3
Stop counting!
as it refers to functionHolder
, not the function (which it itself points to). This could be desirable in some circumstances, but is there a way to write the function so that it calls itself rather than the variable that holds it?
也就是说,是否可以更改仅行functionHolder(counter-1);
,以便通过所有这些步骤仍然得到3
2
1
0
当我们调用 copyFunction(3);
时?我试过 this(counter-1);
但这给了我错误 this is not a function
.
That is, is it possible to change only the line functionHolder(counter-1);
so that going through all these steps still gives 3
2
1
0
when we call copyFunction(3);
? I tried this(counter-1);
but that gives me the error this is not a function
.
推荐答案
使用命名函数表达式:
您可以为函数表达式指定一个实际上私有的名称,并且仅在函数内部可见:
Using Named Function Expressions:
You can give a function expression a name that is actually private and is only visible from inside of the function ifself:
var factorial = function myself (n) {
if (n <= 1) {
return 1;
}
return n * myself(n-1);
}
typeof myself === 'undefined'
此处myself
仅在函数内部可见.
您可以使用此私有名称递归调用该函数.
You can use this private name to call the function recursively.
可以从 FunctionExpression 的 FunctionBody 内部引用 FunctionExpression 中的 Identifier,以允许函数递归调用自身.但是,与 FunctionDeclaration 不同的是,FunctionExpression 中的 Identifier 不能被引用并且不会影响包含 FunctionExpression 的范围.
The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
请注意,直到版本 8 的 Internet Explorer 行为不正确,因为名称实际上在封闭变量环境中可见,并且它引用了实际函数的副本(请参阅 patrick dw'在下面评论).
Please note that Internet Explorer up to version 8 doesn't behave correctly as the name is actually visible in the enclosing variable environment, and it references a duplicate of the actual function (see patrick dw's comment below).
或者您可以使用 arguments.callee
引用当前函数:
Alternatively you could use arguments.callee
to refer to the current function:
var factorial = function (n) {
if (n <= 1) {
return 1;
}
return n * arguments.callee(n-1);
}
ECMAScript 第 5 版禁止在 严格模式中使用 arguments.callee(),然而:
The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode, however:
(来自 MDN):在普通代码中 arguments.callee 指的是封闭函数.这个用例很弱:只需命名封闭函数!此外,arguments.callee 大大阻碍了像内联函数这样的优化,因为如果访问 arguments.callee,必须能够提供对未内联函数的引用.严格模式函数的arguments.callee 是一个不可删除的属性,它在设置或检索时抛出.
(From MDN): In normal code arguments.callee refers to the enclosing function. This use case is weak: simply name the enclosing function! Moreover, arguments.callee substantially hinders optimizations like inlining functions, because it must be made possible to provide a reference to the un-inlined function if arguments.callee is accessed. arguments.callee for strict mode functions is a non-deletable property which throws when set or retrieved.
这篇关于递归调用javascript函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!