【问题标题】:A clearer explanation for recursion and flow of execution in JavaScript?更清楚地解释 JavaScript 中的递归和执行流程?
【发布时间】:2010-10-17 17:40:14
【问题描述】:

我在阅读 Eloquent JavaScript 时遇到了这个谜题示例:

考虑这个难题:从 数字 1 并重复 加 5 或乘以 3,则 无限数量的新数字可以是 产生。你会怎么写 给定一个数字,尝试的函数 找到一系列的加法和 产生那个的乘法 号码?

这是解决方案的代码:

function findSequence(goal) {
  function find(start, history) {
    if (start == goal)
      return history;
    else if (start > goal)
      return null;
    else
      return find(start + 5, "(" + history + " + 5)") ||
             find(start * 3, "(" + history + " * 3)");
  }
  return find(1, "1");
}

print(findSequence(24));

如果 dod find 没有参数 start 和 goal 的值,有人可以澄清它是如何执行的吗?还有递归是怎么发生的?

【问题讨论】:

标签: javascript recursion


【解决方案1】:

当 find 在 findSequence 内部调用时,它可以访问在 findSequence 定义中设置的目标变量。一个简单的例子是:

function outerFunction() {
  var a = 2;
  function innerFunction() {
    alert(a);
  }
  innerFunction();
}
outerFunction();

开始变量是在定义时定义的:

return find(1, "1");

实际上初始变量为 1,目标变量为 24,第一次传递的历史记录为“1”。

编辑:根据 Rob 的评论,闭包实际上并不是造成这种情况的原因,因为 find() 没有在 findSequence() 之外执行,范围界定导致找到目标。

【讨论】:

  • 这真的与闭包有关吗?我认为这只是普通的范围解析:“查找”没有自己的“目标”标识符,因此它解析为封闭范围内的标识符。只有在“findSequence”已经返回后间接调用“find”时,闭包才适用。
  • 是的,确实如此,这不是闭包问题,只是范围问题
【解决方案2】:

如果我正确理解您的问题:最后一行代码是调用 findSequence(),目标为 24。在 findSequence() 中有一个名为 find() 的函数,它被定义然后在返回中调用findSequence 的语句,start 等于 1,history 等于 1。

【讨论】:

    【解决方案3】:

    但是find 没有在没有startgoal 的值的情况下执行。它首先使用start 的值1 执行,而goal 的唯一值是24

    也许您对操作顺序感到困惑。在那里我们看到了一个函数的声明findSequence。在声明期间,不执行任何代码。 findSequence 函数只在稍后执行,在最后一行打印出执行函数的结果。

    findSequence 的声明中,还有另一个函数find 的声明。再一次,它直到稍后才会被执行。 findSequence 函数只有一个 可执行代码行,即调用find(1, "1") 的代码行。执行那一行会触发find 的执行若干次,递归。 find 函数引用了goal;当 Javascript 解释器执行代码时,goal 总是引用 findSequence 的参数,因为在这个例子中 findSequence 只被调用一次,goal 总是具有相同的值,24

    您应该能够看到递归发生的位置。如果start 等于goal,则函数停止;它返回它如何到达该数字的历史。如果start 大于goal,则返回null,表示该路径不是目标编号的路径。如果start 仍小于goal,则该函数尝试调用自身,其起始值加5。如果返回非空值,则返回该值。否则,它会尝试乘以 3 并返回该历史值。

    请注意,尽管此代码可以返回许多数字,但它不能返回所有个数字。例如,如果目标是2,则findSequence 将返回null,因为没有办法从1 开始并通过添加5 或乘以3 到达2

    【讨论】:

    • return find(start + 5, "(" + history + " + 5)") || find(start * 3, "(" + history + " * 3)") ,这条线是如何工作的?
    猜你喜欢
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2014-03-14
    • 2012-05-22
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多