1

この再帰関数がどのように機能するかわかりません:

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

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

   if(n > 0) f(n);

   alert("after: " + n);
}

f(2)​;​

私はこのコードが機能することを理解しようとしましたが、「before 1」、「before 0」、および「after 0」がどのように実行されるかを見ましたが、「after 1」はどのようにこれから発生するのでしょうか?

私はそれがこのように実行されているのを見ます... f(2) は 1 を減算する g を呼び出すので、'n' は 1 になります。 . Alert("before:" + n) がもう一度実行され、0 は 0 より大きくないため、Alert("after:" + n) が実行され、関数は終了しますか?...

編集: @FlorianMargaine と @Cyrille に、この背後にあるロジックを理解するのを手伝ってくれてありがとう。=)

4

4 に答える 4

3

after 1Javascriptでは、パラメータは参照ではなく値で渡されるという事実に由来します。したがって、最初の反復では、if(n > 0) f(n);どの呼び出しを呼び出し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()/g()を再帰的に呼び出しますが、ある時点でn0 に達し、ステートメントでf()呼び出されないため、警告を発して一連の呼び出しを返し始め、最終的に最初のスタック フレームに到達します。ifafter: 0n1

于 2012-06-19T07:05:45.350 に答える