递归调用一个javascript函数 [英] Calling a javascript function recursively

查看:114
本文介绍了递归调用一个javascript函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  / *递归递减到0。 
* /
var functionHolder = function(counter){
output(counter);
if(counter> 0){
functionHolder(counter-1);




$ b $ p $ functionHolder( 3); 会输出 3 2 1 0 。假设我做了以下操作:

  var copyFunction = functionHolder; 

copyFunction(3); 会输出 3 2 1 0 如上。如果我然后更改 functionHolder ,如下所示:

  functionHolder = function(whatever ){
输出(停止计数!);

然后 functionHolder(3); 会给停止计数!,如预期的那样。

copyFunction(3); 现在给出 3 停止计数!,因为它引用 functionHolder ,而不是函数(它本身指向的)。在某些情况下,这可能是可取的,但是有没有办法编写这个函数,让它自己调用它自己而不是变量来保存它?

就是这样吗?可能只改变 functionHolder(counter-1); ,这样经过所有这些步骤仍然会给 3 2 1 0 调用 copyFunction(3); ?我试过 this(counter-1); 但是这给我错误这不是函数

解决方案

使用命名函数表达式:



您可以给函数表达式一个名称这实际上是 private ,并且仅在函数内部可见:

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

这里我自己仅在函数内部可见。



您可以使用此专用名称该函数递归。



请参阅 13。 ECMAScript 5规范的函数定义


FunctionExpression中的标识符可以从在FunctionExpression的FunctionBody中允许函数以递归方式调用它自己。然而,与FunctionDeclaration不同,FunctionExpression中的标识符不能被引用,也不会影响包含FunctionExpression的作用域。

请请注意,Internet Explorer版本8的行为不正确,因为该名称实际上在封闭变量环境中可见,并且引用了实际函数的副本(请参阅下面的 patrick dw 的注释) 。



使用arguments.callee:



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

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



$ b

第5版ECMAScript禁止在 strict mode $ b


(来自 MDN ):在正常的代码参数中..callee指的是封闭功能。这个用例很弱:只需命名封闭函数!此外,arguments.callee基本上阻碍了内联函数之类的优化,因为如果访问arguments.callee,必须提供对非内联函数的引用。用于严格模式函数的arguments.callee是一个不可删除的属性,在设置或检索时抛出。



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

With this, functionHolder(3); would output 3 2 1 0. Let's say I did the following:

var copyFunction = functionHolder;

copyFunction(3); would output 3 2 1 0 as above. If I then changed functionHolder as follows:

functionHolder = function(whatever) {
    output("Stop counting!");

Then functionHolder(3); would give Stop counting!, as expected.

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?

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'

Here myself is visible only inside of the function itself.

You can use this private name to call the function recursively.

See 13. Function Definition of the ECMAScript 5 spec:

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.

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).

Using 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);
}

The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode, however:

(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆