我正在阅读Eloquent JavaScript,我遇到了这个难题的例子:
考虑这个难题:从开始 数字1和反复 加5或乘以3,an 无限量的新数字都可以 产生的。你会怎么写的? 在给定数字的情况下尝试的功能 找到一系列的补充和 产生它的乘法 号码?
以下是解决方案的代码:
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));
如果没有参数start和goal的值,有人可以清楚dod find如何执行吗?递归是怎么发生的?
答案 0 :(得分:5)
但是find
没有<{1}}和start
的值而执行。它首先使用goal
的值1
执行,而start
的唯一值是goal
。
也许你对操作的顺序感到困惑。我们在那里看到函数{em}的声明。24
。在声明期间,不执行任何代码。 findSequence
函数仅在最后一行执行,执行函数的结果将被打印出来。
在findSequence
的声明中,有另一个函数findSequence
的声明。再一次,直到后来它才会被执行。 find
函数只有一个可执行代码行,即调用findSequence
的代码。执行该一行会递归地触发find(1, "1")
执行若干次。 find
函数引用find
;当Javascript解释器执行代码时,goal
始终引用goal
的参数,因为在此示例中findSequence
仅被调用一次,findSequence
始终具有相同的值,goal
。
您应该能够看到递归发生的位置。如果24
等于start
,则函数停止;它返回它到达该数字的历史。如果goal
大于start
,则返回goal
,表示该路径不是目标号码的路径。如果null
仍小于start
,则函数会尝试调用自身,其起始值加上5.如果返回非空值,那么返回的是。否则,它会尝试乘以3并返回该历史值。
请注意,虽然此代码可以返回许多数字,但它无法返回所有数字。例如,如果目标为goal
,2
将返回findSequence
,因为无法从null
开始并通过添加{1
来2
1}}或乘以5
。
答案 1 :(得分:1)
当在findSequence内部调用find时,它可以访问在findSequence的定义中设置的目标变量。一个简单的例子是:
function outerFunction() {
var a = 2;
function innerFunction() {
alert(a);
}
innerFunction();
}
outerFunction();
起始变量是在以下情况下定义的:
return find(1, "1");
有效地将初始开始变量设为1,目标变量为24,并且在第一次过程中具有“1”的历史记录。
编辑:根据Rob的评论,闭包实际上并不是造成这种情况的原因,因为find()没有在findSequence()之外执行,范围确定导致找到目标。答案 2 :(得分:0)
如果我正确理解你的问题:最后一行代码是调用findSequence(),目标是24.在findSequence()中有一个名为find()的函数,它被定义然后在返回时调用findSequence的语句,start等于1,历史等于1。