【问题标题】:Javascript recursive function inside a for loopfor循环内的Javascript递归函数
【发布时间】:2015-07-14 07:25:33
【问题描述】:
var f_drum_min = function myself(a){
  alert(a);
  $f_min_node.push(a);
    for (i=0;i<=$m;i++){
      if ($f_leg[i][1]==a){
          myself($f_leg[i][0]);
      }
    }  
};

myself($f_leg[i][0]); 打破了for 循环,我怎样才能让它在循环中运行多次?

【问题讨论】:

  • var f_drum_min = function myself(a) 似乎不合法。
  • @u_mulder:实际上这是有效的 JavaScript 语法。不过,标识符myself 将只存在于内部函数中。
  • @RocketHazmat 谢谢,现在我知道了更多)
  • 什么是 $f_leg?什么是 $m?如果没有更多信息,很难掌握可能出错的地方。
  • 当 for 循环“中断”时会发生什么?有错误吗?

标签: javascript function for-loop recursion


【解决方案1】:

你的功能充满了坏习惯

我无法改进 this 功能,因为我不知道所有这些外部状态都做了什么。它们的数据类型也不是很明显。

这些都是坏习惯,因为没有办法知道你的函数的效果。它唯一的输入是a,但函数依赖于$f_min_node$f_leg$m

  • 在您调用函数时,这些变量的值是多少?

  • 还有哪些函数会改变这些值?

  • 我将$f_min_node 分配给某个值,然后调用f_drum_min。我怎么会知道$f_min_node 会变?

每次调用函数时,结果都会令人大吃一惊。这些是编写非确定性(“不纯”)函数的麻烦。

在你能解决这些问题之前,在 for 循环中递归是最不你关心的问题

我在这里用 cmets 注释了你的代码

// bad function naming. what??
var f_drum_min = function myself(a){

  // side effect
  alert(a);

  // external state: $f_min_node
  // mutation: $f_min_node
  $f_min_node.push(a);

    // leaked global: i
    // external state: $m
    for (i=0;i<=$m;i++){

      // external state: $f_leg
      // loose equality operator: ==
      if ($f_leg[i][1]==a){
          myself($f_leg[i][0]);
      }
    }  
};

我可以帮助您编写一个使用线性迭代过程的确定性递归函数。最重要的是,它不依赖于任何外部状态,也不会改变输入。

// Number -> Number
var fibonacci = function(n) {
  function iter(i, a, b) {
    if (i === 0)
      return a;
    else
      return iter(i-1, b, a+b);
  }
  return iter(n, 0, 1);
}

fibonacci(6); // 8

for 循环非常原始;命令式程序员几乎会立即使用它,认为这是解决迭代问题的唯一方法。

本可以在此函数中使用for 循环,但以不同的方式思考问题使我能够以不同的方式表达它并完全避免for 循环。

【讨论】:

  • +1 真正解决这个问题。我看了一眼,觉得不值得费力去详细说明所有这些,这是你这样做的道具。
  • @JaredSmith 非常感谢您的反馈 ^.^ 如果我在 10 年前就学会了如何编写更好的函数,我想知道我今天会在哪里......
【解决方案2】:

代码的一个基本问题是,循环变量i 是一个全局变量,因此它被函数的所有递归调用共享。

例如,假设第一次调用该函数。 i 是 0。现在它递归了,假设 if 中的条件永远不会是 true。在第二次通话结束时,i = $m + 1。当你返回第一次调用时,因为i 是全局的,所以第一次调用中的循环结束。我想这不是你想要的。

解决此问题的方法是将i 声明为本地:

for (var i=0;i<=$m;i++){

这可能会或可能不会解决您的所有问题(正如 cmets 中所指出的,我们必须查看更多代码才能识别所有可能的问题),但这是至关重要的第一步。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    相关资源
    最近更新 更多