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

当在没有第二return条语句的情况下使用该函数时,该函数不会为 JavaScript 返回中的每个定义的被调用者产生任何值undefined

所以使用第一个定义,例如loop(9)

  1. 0 < 10,所以我们不执行if-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

在第二种情况下,return loop(x + 1);导致loop返回其他调用返回的任何内容loop

使用非递归示例可能更容易理解:

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函数都在做它们的工作并返回它们的值。内部函数首先被调用 - 它添加1x(从 开始0),并将其值返回到 next add_1,它添加一个并将其返回到 next add_1

...但如果你不返回值,什么都不会发生。

使用递归,这是相同的想法。

您正在返回您正在调用的函数的返回值。

不需要这样做。
有时,递归是关于遍历一棵树并修改子节点——比如将每个第二个 DOM 节点更改为红色,并将每个父节点的第一个子节点更改为蓝色......

那里没有您需要的返回值。
您只需要设置检查,这样您就不会尝试递归到无穷大或最终尝试修改不存在的事物的属性。

但是对于收银机或你确实想知道一个值是否存在的循环,那么你所做的与说 相同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

此递归调用的评估顺序将从最后一次调用开始。首先评估的函数是 loop(10),它返回值 10。下一个是 loop(9),依此类推。想一想 loop(9) 被调用时的样子:

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

loop(9) 将返回未定义。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 回答