为什么这个递归函数返回undefined?

时间:2016-09-04 21:53:04

标签: javascript recursion

我正在尝试编写一个使用递归组合两个字符串的函数。我的代码在下面,但我不知道为什么函数返回undefined,特别是当我在基本情况下的console.log时它并没有打印undefined而是正确的值。

var str3=""
function merge(str1,str2){
    if(str1.length==0||str2.length==0){
        console.log(str3)
        return str3;
    }
    else{
        str3=str3+str1.substring(0,1)+str2.substring(0,1);
        merge(str1.substring(1,str1.length),str2.substring(1,str2.length))
    }
}

merge("AAA","BBB") //--> returns undefined but the console.log(str3) gives correct answer

2 个答案:

答案 0 :(得分:11)

<强>解释

问题是你没有返回递归调用的结果,因此在解析merge的整个调用时它是未定义的。

让我一步一步地指导您执行:

  1. 使用参数"AAA""BBB",它们的长度不是0 ,去别的。进入其他地方后,str3"AB",请致电merge("AA", "BB")
  2. 使用参数"AA""BB",其长度不为0,去别的地方。进入其他地方后,str3现在为"ABAB",请致电merge("A", "B")
  3. 使用参数"A""B",其长度不为0 ,去别的。进入其他地方后,str3现在为"ABABAB",请致电merge("", "")
  4. 使用空字符串参数,长度为0.现在转到if语句,其中{{ 1}}被记录并返回。
  5. 由于str3调用已经解决(返回时为merge("", "")),我们会继续调用{{{} 1}},因此“调高”调用堆栈。
  6. 我们从调用"ABABAB"中的else分支开始。该调用中没有更多的语句或表达式,因此它已得到解决。 没有返回语句,因此默认情况下会返回merge("A", "B") 。我们“调高”调用堆栈来调用我们离开的merge("A", "B")
  7. 我们从调用undefined中的else分支处开始。该调用中没有更多的语句或表达式,因此它已得到解决。同样,没有返回语句,因此默认情况下返回merge("AA", "BB")。我们“调高”调用堆栈来调用我们离开的merge("AA", "BB")
  8. 我们从调用undefined中的else分支处开始。该调用中没有更多的语句或表达式,因此它已得到解决。同样,没有返回语句,因此默认情况下返回merge("AAA", "BBB")。没有更多的电话,所以一切都已解决 - 而merge("AAA", "BBB")返回undefined

TL; DR:在else分支的每次调用中都不返回递归调用,因此merge("AAA", "BBB")的值将返回到调用undefined。调用str3不返回任何内容,它返回merge("A", "B")。所有其他调用也是如此 - 它们在else分支中没有return语句,因此返回merge("A", "B")。解决所有呼叫后,将返回undefined

<强>解决方案

解决方案是简单地将undefined添加到递归调用中。这样,每次调用的结果都会被返回,将undefined的最终返回值“委托”到调用堆栈中 - 调用返回return,而不是str3

由于我们现在返回调用的结果,上面的步骤6,7和8现在有一个返回语句。这意味着我们不会返回"ABABAB",而是返回undefined。这是因为undefined返回了str3,这是merge("", "")的值。然后在调用"ABABAB"中返回该结果,因为新添加了str3语句,然后在调用merge("A", "B")中返回,依此类推,直到调用完全解决,并返回return的价值。

这是新代码:

merge("AA", "BB")

之前,str3会收到值var str3 = ""; function merge(str1, str2) { if(str1.length == 0 || str2.length == 0) { console.log(str3); return str3; } else { str3 = str3 + str1.substring(0, 1) + str2.substring(0, 1); return merge(str1.substring(1, str1.length), str2.substring(1, str2.length)); //we return the recursive call } } var mergedString = merge("AAA","BBB"); //mergedString is "ABABAB"。由于我们现在返回递归调用,因此返回所有内容,因此返回mergedString的值,并将其存储到变量undefined中。

答案 1 :(得分:0)

如何在this指南中查看您必须return递归函数:

var str3=""
function merge(str1,str2){
    if(str1.length==0||str2.length==0){
        console.log(str3)
        return str3;
    }
    else{
        str3=str3+str1.substring(0,1)+str2.substring(0,1);
        return merge(str1.substring(1,str1.length),str2.substring(1,str2.length))
    }
}

merge("AAA","BBB")