1

我看不到这个递归函数是如何工作的:

function f(n) { g(n-1) }

function g(n) {
   alert("before: " + n);

   if(n > 0) f(n);

   alert("after: " + n);
}

f(2)​;​

我试图理解这段代码的工作原理,我看到了“1 之前”、“0 之前”和“0 之后”是如何执行的,但是......“1 之后”是如何产生的?

我看到它是这样执行的...... f(2) 调用 g 减去 1,所以 'n' 变为 1。 Alert("before: " + n) 被执行,1 大于 0,所以它会调用自己并减去 1 .alert("before:" + n) 再次执行,0不大于0所以会执行Alert("after:" + n) 函数结束?...

编辑:感谢@FlorianMargaine 和@Cyrille 帮助我理解这背后的逻辑。=)

4

4 回答 4

3

after 1源于在 Javascript 中,参数是按值而不是按引用传递的。所以在第一次迭代中,调用if(n > 0) f(n);which 调用g(n-1)不会递减n。它的值在if(n > 0) f(n)返回时保留,并保持其值 1。

这是一个调用图:

f(2) calls f(n) with n=2
├─ calls g(n-1), which is g(2-1) = g(1)
│   ├─ g(1) alerts "before: 1"
│   ├─ g(1), n > 0 ==> call f(1)
│   │   ├─ f(1) calls f(n) with n=1, but it's not the same "n"
│   │   │  as we're in another call (see the call tree?)
│   │   │   ├─ calls g(n-1), which is g(1-1) = g(0)
│   │   │   │   ├─ g(0) alerts "before: 0"
│   │   │   │   ├─ n == 0 ==> don't call f(n)
│   │   │   │   └─ g(0) alerts "after: 0"
│   │   └─ and that's all for f(1)
│   └─ g(1) alerts "after: 1"
└─ and that's all
于 2012-06-19T06:49:28.203 回答
1

查看调用顺序:

Calls f() with parameter 2
f() calls g() with parameter 2-1 -> 1
g() alerts "before: 1"
since n > 0, g() calls f() with parameter 1 -- and blocks further execution of current g() with parameter 1 - in other words, it goes down in "funception"
f() calls g() with parameter 1-1 -> 0
g() alerts "before: 0"
since n === 0, it skips the if
g() alerts "after: 0"
finally, the blocked execution can resume because the inner function has finished executing, so it alerts "after: 1"

它并不是真正的“阻塞”,它只是在执行当前函数的其余部分之前执行内部函数。

为了清楚地理解逻辑,只需尝试通过“说出来”来遵循它。

于 2012-06-19T06:48:18.447 回答
0

现在更有意义?n ≤ 0 是基本情况。

function g(n) {
   alert("before: " + n);

   if(n > 0) g(n - 1);

   alert("after: " + n);
}

g(2)​;​
于 2012-06-19T06:50:02.513 回答
0

每个函数调用最终都会返回。代码递归调用f()/ ,但在某些时候达到 0 并且没有在语句中调用,因此它会发出警报并开始返回调用链,最终到达第一个堆栈帧,其中is 。g()nf()ifafter: 0n1

于 2012-06-19T07:05:45.350 回答