小编典典

递归调用javascript函数

javascript

我可以在变量中创建一个递归函数,如下所示:

/* 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


阅读 466

收藏
2020-05-01

共1个答案

小编典典

使用命名函数表达式:

您可以为函数表达式指定一个实际上是 私有 的名称,并且只有在函数内部才能看到:

var factorial = function myself (n) {
    if (n <= 1) {
        return 1;
    }
    return n * myself(n-1);
}
typeof myself === 'undefined'

下面myself该函数的可见里面只有 自己。

您可以使用此私有名称来递归调用该函数。

请参阅[13. FunctionDefinitionECMAScript 5规范:

可以从FunctionExpression的FunctionBody内部引用FunctionExpression中的标识符,以允许该函数以递归方式调用自身。但是,与FunctionDeclaration中的功能不同,FunctionExpression中的Identifier不能从中引用,也不会影响包围FunctionExpression的范围。

请注意,版本8之前的InternetExplorer的行为不正确,因为该名称实际上在封闭的变量环境中可见,并且它引用了实际功能的副本(请参见下面的_patrick dw_ 的注释)。

使用arguments.callee:

或者,您可以arguments.callee用来引用当前函数:

var factorial = function (n) {
    if (n <= 1) {
        return 1;
    }
    return n * arguments.callee(n-1);
}

ECMAScript的第五版禁止在严格模式下使用arguments.callee(),但是:

(来自MDN):在常规代码中arguments.callee指的是封闭函数。这种用例很弱:只需命名封闭函数即可!此外,arguments.callee实质上阻碍了诸如内联函数之类的优化,因为如果访问arguments.callee,必须使其能够提供对未内联函数的引用。严格模式功能的arguments.callee是不可删除的属性,在设置或检索时会抛出该属性。

2020-05-01