JavaScript中递归和执行流的更清晰解释?

JavaScript中递归和执行流的更清晰解释?,javascript,recursion,Javascript,Recursion,我在阅读有说服力的JavaScript时,遇到了这个谜题示例: 考虑一下这个难题:从 数字1,然后重复 加5或乘以3,即 可以创建无限数量的新数字 产生。你会怎么写一篇文章 函数,给定一个数字,它将尝试 找到一系列的加法和 产生这个的乘法 号码 以下是解决方案的代码: function findSequence(goal) { function find(start, history) { if (start == goal) return history; el

我在阅读有说服力的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的值,有人能解释一下它是如何执行的吗?递归是如何发生的?

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

function outerFunction() {
  var a = 2;
  function innerFunction() {
    alert(a);
  }
  innerFunction();
}
outerFunction();
开始变量在以下情况下定义:

return find(1, "1");
在第一次通过时,初始开始变量为1,目标变量为24,历史记录为“1”


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

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

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

也许你对操作顺序感到困惑。在这里我们可以看到函数的声明,
findSequence
。在声明期间,不执行任何代码。
findSequence
函数只在最后一行执行,在最后一行,执行函数的结果会打印出来

findSequence
的声明中,有另一个函数
find
的声明。再一次,它直到稍后才被执行。
findSequence
函数只有一行可执行代码,调用
find(1,“1”)
。执行这一行会递归地触发执行
find
若干次。
find
函数引用
目标
;当Javascript解释器执行代码时,
goal
始终引用
findSequence
的参数,并且由于在本例中,
findSequence
只调用一次,
goal
始终具有相同的值,
24

您应该能够看到递归发生的位置。如果
start
等于
goal
,则函数停止;它返回它如何得出该数字的历史记录。如果
start
大于
goal
,则返回
null
,表示该路径不是目标编号的路径。如果
start
仍然小于
goal
,则函数会尝试使用其start值加5来调用自己。如果它返回一个非空值,那么这就是返回的值。否则,它将尝试乘以3并返回该历史值


请注意,尽管此代码可以返回许多数字,但不能返回所有数字。例如,如果目标是
2
,那么
findSequence
将返回
null
,因为无法从
1
开始,通过添加
5
或乘以
3
到达
2
,这真的与闭包有关吗?我认为这只是普通的范围解析:“find”本身没有“goal”标识符,因此它解析为封闭范围中的标识符。只有在“findSequence”已经返回后间接调用“find”时,闭包才会应用。是的,事实上,这不是闭包问题,只是范围问题。请参见和
返回find(开始+5,(“+history+”+5)”)| find(开始*3,(“+history+”*3)”)
,这行代码是如何工作的?