简体   繁体   English

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

[英]Why does this recursive function return undefined?

I'm attempting to write a function that combines two strings using recursion. 我正在尝试编写一个使用递归组合两个字符串的函数。 My code is below but I don't know why the function returns undefined especially when I console.log within the base case and it does not print undefined but instead the correct value. 我的代码在下面,但我不知道为什么函数返回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

Explanation 说明

The problem is that you don't return the recursive call's result, thus it is undefined when the whole call to merge is resolved. 问题是您没有返回递归调用的结果,因此在解析整个merge调用时它是未定义的。

Let me take you through the execution, step-by-step: 让我一步一步带你完成执行:

  1. With arguments "AAA" and "BBB" , their lengths are not 0, go to else. 使用参数"AAA""BBB" ,它们的长度不是0,转到其他地方。 Once in else, str3 is "AB" , call merge("AA", "BB") . 一旦进入else, str3"AB" ,调用merge("AA", "BB")
  2. With arguments "AA" and "BB" , their lengths are not 0, go to else. 使用参数"AA""BB" ,它们的长度不是0,转到其他地方。 Once in else, str3 is now "ABAB" , call merge("A", "B") . 一旦进入else, str3现在是"ABAB" ,调用merge("A", "B")
  3. With arguments "A" and "B" , their lengths are not 0, go to else. 使用参数"A""B" ,它们的长度不是0,转到其他地方。 Once in else, str3 is now "ABABAB" , call merge("", "") . 一旦进入else, str3现在是"ABABAB" ,调用merge("", "")
  4. With empty string arguments, length is 0. Now go to the if statement, where str3 is logged, and returned. 使用空字符串参数,长度为0.现在转到if语句,其中记录了str3 ,并返回。
  5. Since the merge("", "") call has resolved (to "ABABAB" as it is returned), we continue where we left off in the call merge("A", "B") , thus going "up" the call stack. 由于merge("", "")调用已解决(返回时为"ABABAB" ),我们继续在调用merge("A", "B")停止的地方,从而“向上”调用堆栈。
  6. We start where we left off in call merge("A", "B") , in the else branch. 我们从其他分支中的呼叫merge("A", "B")中断的地方开始。 There are no more statements or expressions in that call, so it's resolved. 该调用中没有更多的语句或表达式,因此它已得到解决。 There are no return statements, so by default it returns undefined . 没有返回语句,因此默认情况下它返回undefined We go "up" the call stack to call merge("AA", "BB") where we left off. 我们“调高”调用堆栈以调用merge("AA", "BB")我们离开的地方。
  7. We start where we left off in call merge("AA", "BB") , in the else branch. 我们从其他分支中的呼叫merge("AA", "BB")中断的地方开始。 There are no more statements or expressions in that call, so it's resolved. 该调用中没有更多的语句或表达式,因此它已得到解决。 Again, there are no return statements so by default it returns undefined . 同样,没有return语句,所以默认情况下它返回undefined We go "up" the call stack to call merge("AAA", "BBB") where we left off. 我们“调高”调用堆栈以调用merge("AAA", "BBB")我们离开的地方。
  8. We start where we left off in call merge("AAA", "BBB") , in the else branch. 我们从其他分支中的呼叫merge("AAA", "BBB")中断开始。 There are no more statements or expressions in that call, so it's resolved. 该调用中没有更多的语句或表达式,因此它已得到解决。 Again, there are no return statements so by default it returns undefined . 同样,没有return语句,所以默认情况下它返回undefined There are no more calls, so everything's resolved - and merge("AAA", "BBB") returns undefined . 没有更多的调用,所以一切都解决了 - 并且merge("AAA", "BBB")返回undefined

TL;DR: The recursive call is not returned on each call in the else branch, so the value of str3 is returned to the call merge("A", "B") . TL; DR:在else分支的每次调用中都不返回递归调用,因此str3的值返回到调用merge("A", "B") The call merge("A", "B") does not return anything, it returns undefined . 调用merge("A", "B")不返回任何内容,它返回undefined The same goes for all other calls - they have no return statement in the else branch so undefined is returned. 所有其他调用都是一样的 - 它们在else分支中没有return语句,因此返回undefined When all calls are resolved, undefined is returned. 解析所有调用后,将返回undefined


Solution

The solution is to simply prepend return to your recursive calls. 解决方案是简单地将return到递归调用。 That way, the result of each call would be returned, 'delegating' the final returned value of str3 up the call stack - the call returns "ABABAB" , not undefined . 这样,每次调用的结果都会返回,将str3的最终返回值“委托”到调用堆栈中 - 调用返回"ABABAB" ,而不是undefined

Since we now return the result of the call, steps 6, 7, and 8 above now have a return statement . 由于我们现在返回调用的结果, 现在上面的步骤6,7和8 都有一个return语句 That means we don't return undefined , but instead str3 . 这意味着我们不会返回undefined ,而是返回str3 This is because merge("", "") returned "ABABAB" , which is the value of str3 . 这是因为merge("", "")返回"ABABAB" ,这是str3的值。 That result is then returned in call merge("A", "B") because of the new added return statement, which is then returned in call merge("AA", "BB") , and so on, until the call is completely resolved, and the returns the value of str3 . 然后在调用merge("A", "B")返回该结果merge("A", "B")因为新添加的return语句然后在调用merge("AA", "BB") ,依此类推,直到调用为止完全解决了,并返回str3的值。

Here's the new code: 这是新代码:

 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" 

Before, mergedString would have received the value undefined . 之前, mergedString会收到undefined值。 Since we now return the recursive calls, everything returned accordingly thus the value of str3 is returned, being stored into variable mergeString . 由于我们现在返回递归调用,因此返回所有内容,因此返回str3的值, str3其存储到变量mergeString

As you can see in this guide you have to return the result of the recursive call: 正如您在指南中所看到的,您必须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")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM