1

いくつかの再帰を試していたところ、混乱することに気付きました。いくつかのコード例で説明しましょう:

function loop(x) {
  if (x >= 10) 
    return x;
  loop(x + 1); // the recursive call
}
loop(0);

上記の呼び出しは を返しますundefined。に変更すると

function loop(x) {
  if (x >= 10) 
    return x;
  return loop(x + 1); // the recursive call
}
loop(0);

10その後、正しく戻ります。

なぜこれが起こるのですか?return句はスタックにどのように影響しますか?

PS:同様の質問

編集: これは、私が理解したことの概要を示す簡単な画像です。(絵の具は一切持っていません。)そうですか?そうでない場合、どこで間違っていますか?

4

6 に答える 6

4

2 番目のreturnステートメントなしで関数を使用すると、関数は JavaScript の定義ごとに呼び出し先に値を返しませんundefined

したがって、最初の定義を使用すると、たとえばloop(9)次のようになります。

  1. 0 < 10ifであるため、 -clause 本体は実行せず、単に を呼び出しますloop(10)
  2. loop(10)を返しますが10、この値は使用しません。
  3. 関数ループが終了し、他の値が返されなかったため、 が返されますundefined
于 2013-02-23T18:03:26.687 に答える
4

Javascript 関数から戻らない場合、最後に暗黙の「未定義の戻り」があります。

function loop(x) {
  if (x >= 10)
    return x;
  loop(x + 1); // the recursive call
  return undefined;
}

ご覧のとおり、再帰呼び出しが呼び出され、その戻り値が無視されています。これは、次のような関数を呼び出したときに起こることとまったく同じですconsole.log。関数が呼び出されて副作用を実行しますが、最終的に戻り値を破棄します。

于 2013-02-23T18:08:51.843 に答える
2

関数は、値を直接の呼び出し元に返すだけです。の場合loop(0)if条件が満たさreturn x;れていないため、実行されず、関数には他のreturnステートメントがないため、何も返されません。

で呼び出すとloop(10)、条件が満たされ、 が返され10ます。

2 番目のケースでは、他の呼び出しが返すものは何でもreturn loop(x + 1);返します。looploop

非再帰的な例で理解しやすいかもしれません:

function bar() {
    return 42;
}

function foo1() {
    bar();
}

function foo2() {
    return bar();
}

//
foo1(); // undefined
foo2(); // 42

foo1を呼び出しますbarが、戻り値には何もしません。return内にステートメントがないためfoo、関数は何も返しません。

foo2一方、 の戻り値を返しますbar

于 2013-02-23T18:04:19.570 に答える
1
function count_to_3 (x) {
    x = x || 0;
    if (x === 3) { return x; }
    return count_to_3(x + 1);
}

count_to_3();

これは、次のようなことを言っているのと同じです。

function add_1 (x) { return x + 1; }

function count_to_3 () {
    var x = 0;
    x = add_1( add_1( add_1(x) ) );

    return x;
}

count_to_3();

add_1関数はそれぞれの役割を果たし、その値を返します。内側の関数が最初に呼び出されます。これは(で始まる) に追加1し、その値を nextに返します。x0add_1add_1

...しかし、値を返さないと何も起こりません。

再帰の場合も同じ考えです。

呼び出している関数の戻り値を返しています。

これを行う必要はありません。
再帰とは、ツリーをたどって子を変更することである場合があります。たとえば、2 つおきの DOM ノードを赤に変更し、すべての親ノードの最初の子を青に変更するなどです。

そこに必要な戻り値はありません。
無限に再帰しようとしたり、存在しないもののプロパティを変更しようとしたりしないように、チェックを設定する必要があるだけです。

しかし、キャッシュ レジスターや値が存在するかどうかを知りたい for ループの場合、その値が返されるとreturn add_1( add_1( add_1(0) ) );仮定して、あなたがしていることは と言っているのと同じです。add_1

return ステートメントを持たない関数はすべて戻りますundefined( で呼び出された場合を除きnewますが、新しいオブジェクトを取得しても、それも役に立ちません)。

于 2013-02-23T18:16:04.407 に答える
0

x<10 の場合、ループ関数は値を返さないため、return loop(x + 1);「未定義」になります。10 に達するとすぐに、return x;ステートメントが開始され、戻り値が取得されます。

再帰関数として使用するという事実は、ここでは何の違いもありません。

于 2013-02-23T18:05:18.133 に答える
-1

この再帰呼び出しが評価される順序は、最後の呼び出しから下になります。最初に評価される関数は、値10を返すloop(10)です。次はloop(9)などになります。loop(9)が呼び出されたときにどのように見えるかを考えてください。

loop(9) {
    if (x >= 10) 
        return x;
    10
}

loop(9)はundefinedを返します。loop(8)も同様になります...など。

逆に、再帰呼び出しの値を返すと、次のようになります。

loop(9) {
    if (x >= 10) 
        return x;
    return 10
}

そして、最初の関数呼び出しが実行されるまでに、次のようになります。

loop(0) {
    if (x >= 10) 
        return x;
    return 10
}

ポイントを示すためにjsfiddleを作成しました:http: //jsfiddle.net/TSnxp/

于 2013-02-23T18:28:26.500 に答える