来自Haverbeke第二版的第50页。我添加了几个console.log来试图更好地跟踪进度。
function power(base, exponent) {
if (exponent == 0) {
console.log("line 5 " + base + " " + exponent);
return 1;
}
else
console.log("line 10 " + base + " " + exponent);
return base * power(base, exponent -1);
}
console.log(power(2,3));
//输出
line 10 2 3
line 10 2 2
line 10 2 1
line 5 2 0
8
//
我希望最终输出为1
,因为当if (exponent == 0)
为真时,下一个语句为return 1;
,但它似乎再次输入else
返回8.但return
不应该让我们离开这个职能部门。
显然是一个新手,或者不会被困在一本据称是初学者书的第50页。
感谢您的帮助。
答案 0 :(得分:2)
每当函数进入“else”分支时,都会创建一个新的堆栈帧,等待递归调用的结果。您可以逐步想象评估:
power(2, 3)
进入else
分支,然后返回base * power(base, exponent - 1)
。
2 * power (2, 2)
进入else
分支,然后返回base * power(base, exponent - 1)
。
2 * (2 * power (2, 1))
进入else
分支,然后返回base * power(base, exponent - 1)
。
2 * (2 * (2 * power (2, 0)))
进入if
分支,然后返回1
。
您最终可以评估结果:2 * (2 * (2 * 1))
,即8
。
答案 1 :(得分:2)
函数调用power(2,3)
的最终结果不是最后一次返回,而是后续内部函数调用返回值的组合。让我们解构递归函数:
power(2,3)
返回2 * power(2,2)
power(2,2)
返回2 * power(2,1)
power(2,1)
返回2 * power(2,0)
power(2,0)
返回1
总的来说,power(2,3)
会返回2 * 2 * 2 * 1
,等于8
。
答案 2 :(得分:1)
return
语句退出函数的一次调用。为了到达return 1;
行,该函数将被多次调用(基于指数的原始值)。
第一次调用是
console.log(power(2,3));
在函数内部,后续调用发生在这里:
return base * power(base, exponent -1);
每个人都会对应return
。
哦,正如@TJCrowder在评论中指出的那样,该代码不正确:else
部分应该包含在{ }
中:
if (exponent == 0) {
console.log("line 5 " + base + " " + exponent);
return 1;
}
else {
console.log("line 10 " + base + " " + exponent);
return base * power(base, exponent -1);
}
我假设丢失的{ }
包装器是转录错误。