为了账号安全,请及时绑定邮箱和手机立即绑定

递归调用javascript函数

递归调用javascript函数

慕姐4208626 2019-11-06 10:35:50
我可以在变量中创建一个递归函数,如下所示:/* 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。
查看完整描述

3 回答

?
Cats萌萌

TA贡献1805条经验 获得超9个赞

使用命名函数表达式:

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


var factorial = function myself (n) {

    if (n <= 1) {

        return 1;

    }

    return n * myself(n-1);

}

typeof myself === 'undefined'

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


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


请参阅13. Function DefinitionECMAScript 5规范:


可以从FunctionExpression的FunctionBody内部引用FunctionExpression中的标识符,以允许该函数以递归方式调用自身。但是,与FunctionDeclaration中的功能不同,FunctionExpression中的Identifier不能从中引用,也不会影响包围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的第五版禁止在严格模式下使用arguments.callee(),但是:


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


查看完整回答
反对 回复 2019-11-06
?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

您可以使用arguments.callee [MDN]来访问函数本身:


if (counter>0) {

    arguments.callee(counter-1);

}

但是,这将在严格模式下中断。


查看完整回答
反对 回复 2019-11-06
?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

我知道这是一个古老的问题,但是我想我会提出另外一个解决方案,如果您想避免使用命名函数表达式,可以使用该解决方案。(不是说您应该或不应该避免使用它们,只是提出另一种解决方案)


  var fn = (function() {

    var innerFn = function(counter) {

      console.log(counter);


      if(counter > 0) {

        innerFn(counter-1);

      }

    };


    return innerFn;

  })();


  console.log("running fn");

  fn(3);


  var copyFn = fn;


  console.log("running copyFn");

  copyFn(3);


  fn = function() { console.log("done"); };


  console.log("fn after reassignment");

  fn(3);


  console.log("copyFn after reassignment of fn");

  copyFn(3);


查看完整回答
反对 回复 2019-11-06
  • 3 回答
  • 0 关注
  • 320 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信