我可以像这样在变量中创建一个递归函数:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
这样,functionHolder(3);
将输出 3
2
1
0
。假设我做了以下事情:
var copyFunction = functionHolder;
copyFunction(3);
将输出 3
2
1
0
作为以上。如果我随后更改 functionHolder
如下:
functionHolder = function(whatever) {
output("Stop counting!");
然后 functionHolder(3);
会像预期的那样给出 Stop counting!
。
copyFunction(3);
现在给出 3
Stop counting!
因为它指的是 functionHolder
,而不是函数(它本身指向)。这在某些情况下可能是可取的,但是有没有一种方法可以编写函数,使其调用自身而不是保存它的变量?
也就是说,是否有可能仅 functionHolder(counter-1);
行,以便完成所有这些步骤仍然可以得到3
2
1
0
当我们调用 copyFunction(3);
时?我尝试了 this(counter-1);
但这给了我错误 this is not a function
。
最佳答案
使用命名函数表达式:
您可以为函数表达式指定一个名称,该名称实际上是私有(private)的,并且仅在函数内部可见:
var factorial = function myself (n) {
if (n <= 1) {
return 1;
}
return n * myself(n-1);
}
typeof myself === 'undefined'
这里 myself
仅在函数内部可见。
您可以使用这个私有(private)名称递归调用该函数。
参见 13. Function Definition
ECMAScript 5 规范:
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请在下面发表评论)。
使用 arguments.callee:
或者你可以使用 arguments.callee
引用当前函数:
var factorial = function (n) {
if (n <= 1) {
return 1;
}
return n * arguments.callee(n-1);
}
ECMAScript 第 5 版禁止在 strict mode 中使用 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 - 递归调用javascript函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7065120/