Javascript 递归函数:返回null

Javascript 递归函数:返回null,javascript,recursion,Javascript,Recursion,这个来自雄辩JavaScript的特殊谜题已经在其他地方被问到了,但我还没有找到一个与我提到的具体问题相关的谜题 函数findSolutiontarget{ 函数findstart、历史{ 如果开始=目标 回归历史; 否则,如果开始>目标 返回null; 其他的 返回findstart+5,`${history}+5`|| findstart*3,`${history}*3`; } 返回find1,1; } console.logfindSolution13; // 1 * 3 + 5 +5 。

这个来自雄辩JavaScript的特殊谜题已经在其他地方被问到了,但我还没有找到一个与我提到的具体问题相关的谜题

函数findSolutiontarget{ 函数findstart、历史{ 如果开始=目标 回归历史; 否则,如果开始>目标 返回null; 其他的 返回findstart+5,`${history}+5`|| findstart*3,`${history}*3`; } 返回find1,1; } console.logfindSolution13; // 1 * 3 + 5 +5 。。。下面是调用堆栈:

find1,1 find6,1+5 找到11,1+5+5 找到16,1+5+5+5 太大 查找33,1+5+5*3 太大 查找18,1+5*3 太大 查找3,1*3 find8,1*3+5 查找13,1*3+5+5 建立 我的问题涉及如何返回null;在这里工作。我想更好地理解这条语句是如何导致find返回先前计算的目标参数的;e、 g.,find33,…->查找18,…->发现3。。。我知道如何找到11+5。。将调用传递给find11*3..,但我不明白如何查找11*3。。将调用传递给find6*3。。然后查找1*3,…,正如上面的调用堆栈所示

我知道如何找到11+5。。将调用传递给find11*3..,但我不明白如何查找11*3。。将调用传递给find6*3。。然后找到1*3

首先请注意,find可能返回两种类型的内容:非空字符串历史记录或null。第一个是真实的价值观,第二个是虚假的价值观

您知道find16,1+5+5+5返回null,因此计算| |-表达式的另一部分,即find33,1+5+5*3

就像| |的左部分可以返回null一样,它的右部分也可以返回null。在这种情况下,整个表达式向父调用返回null,父调用也是由这样一个| |表达式生成的

因此,这里也发生了同样的事情,但递归树的级别更高。上述情况发生在find11的更高级别上,1+5+5正在执行。它最终返回null | | null,即null,因此在更高的级别上,它转到自己的| |表达式的另一端,并计算find18,1+5*3。这一次也会立即返回null。所以我们又有了空| |空,回溯这个词!到递归树中的更高级别

父母 递归意味着——当函数执行时——对同一函数进行新的调用。我调用父函数执行递归调用,并等待该调用返回一个返回值

这个孩子也可能成为一个更嵌套的孙子调用的家长。因此,您有一堆未完成的函数执行。当其中最深的一个返回一个值时,它上面的一个将唤醒并接收该值:然后它可以继续并进行另一个子调用,类似的场景将重复。如果它不再进行此类调用,它将向其父回溯返回一个值,而父回溯一直在等待递归调用返回一个值

将整个递归过程想象成一个堆栈。当一些代码调用此函数时,调用方的执行上下文被推送到堆栈上,执行继续执行该函数。此执行上下文包含启动代码从调用函数的点开始所需的所有内容。它有变量及其值,在代码中进行函数调用的确切位置,传递给该函数调用的参数等等

然后函数可以调用自己,因此它自己的执行上下文也会被推到调用堆栈的堆栈上,因此堆栈可能会增长。但在某个时刻,函数将返回一个值,堆栈将展开:上一个执行上下文将被恢复,父级将从它进行递归调用的位置继续执行。此调用堆栈清空时,执行结束

我知道如何找到11+5。。将调用传递给find11*3..,但我不明白如何查找11*3。。将调用传递给find6*3。。然后找到1*3

首先请注意,find可能返回两种类型的内容:非空字符串历史记录或null。第一个是真实的价值观,第二个是虚假的价值观

您知道find16,1+5+5+5返回null,因此计算| |-表达式的另一部分,即find33,1+5+5*3

就像| |的左部分可以返回null一样,它的右部分也可以返回null。在这种情况下,整个表达式向父调用返回null,父调用也是由这样一个| |表达式生成的

因此,这里也发生了同样的事情,但递归树的级别更高。上述情况发生在更高级别的find11,1+5+5为executi时 ng。它最终返回null | | null,即null,因此在更高的级别上,它转到自己的| |表达式的另一端,并计算find18,1+5*3。这一次也会立即返回null。所以我们又有了空| |空,回溯这个词!到递归树中的更高级别

父母 递归意味着——当函数执行时——对同一函数进行新的调用。我调用父函数执行递归调用,并等待该调用返回一个返回值

这个孩子也可能成为一个更嵌套的孙子调用的家长。因此,您有一堆未完成的函数执行。当其中最深的一个返回一个值时,它上面的一个将唤醒并接收该值:然后它可以继续并进行另一个子调用,类似的场景将重复。如果它不再进行此类调用,它将向其父回溯返回一个值,而父回溯一直在等待递归调用返回一个值

将整个递归过程想象成一个堆栈。当一些代码调用此函数时,调用方的执行上下文被推送到堆栈上,执行继续执行该函数。此执行上下文包含启动代码从调用函数的点开始所需的所有内容。它有变量及其值,在代码中进行函数调用的确切位置,传递给该函数调用的参数等等


然后函数可以调用自己,因此它自己的执行上下文也会被推到调用堆栈的堆栈上,因此堆栈可能会增长。但在某个时刻,函数将返回一个值,堆栈将展开:上一个执行上下文将被恢复,父级将从它进行递归调用的位置继续执行。当调用堆栈被清空时,执行结束。

如果您不知道,可能需要阅读相关内容。答案是| |运算符确定null为falsy,并尝试从调用findstart*3、“+history+”*3Do findSolution2开始的第二条路径,您将看到OR同时具有两个falsy值的结果。顺便说一句,你的引号是错的。原来的版本实际上使用了模板文本,但我从其他问题中复制了这个,所以没有注意到。编辑它。@PatrickRoberts我知道那里发生了什么。我不理解的是当| |两边的两个表达式都是falsy/null时会发生什么。我希望它随后将调用返回到原始find1“1”。我希望它随后将调用返回到原始find1“1”。。。是的,它是空的。记住,目标仍然是一样的。如果你不知道的话,你可能想了解一下。答案是| |运算符确定null为falsy,并尝试从调用findstart*3、“+history+”*3Do findSolution2开始的第二条路径,您将看到OR同时具有两个falsy值的结果。顺便说一句,你的引号是错的。原来的版本实际上使用了模板文本,但我从其他问题中复制了这个,所以没有注意到。编辑它。@PatrickRoberts我知道那里发生了什么。我不理解的是当| |两边的两个表达式都是falsy/null时会发生什么。我希望它随后将调用返回到原始find1“1”。我希望它随后将调用返回到原始find1“1”。。。是的,它是空的。请记住,目标保持不变。这一点解释得很好,我想我已经接近理解这一点了,但是你能编辑一下答案,为我详细介绍一下家长电话吗?什么是家长电话?例如,它是最后一个truthy表达式吗?递归意味着在函数执行时进行新调用。我调用父对象,即进行递归调用并等待该调用返回返回值的父对象。该子调用也可能成为更嵌套的孙子调用的父调用。因此,您有一堆未完成的函数执行。当Desthest返回一个高于该值的值时,它可以继续进行另一个子调用。请参阅addition to answer。感谢您在此处提供的深入回答。这一点解释得很好,我想我已接近理解,但您能否编辑回答以为我详细说明父调用?什么是家长电话?例如,它是最后一个truthy表达式吗?递归意味着在函数执行时进行新调用。我调用父对象,即进行递归调用并等待该调用返回返回值的父对象。该子调用也可能成为更嵌套的孙子调用的父调用。因此,您有一堆未完成的函数执行。当Desthest返回一个值时,它可以继续并进行另一个子调用。请参阅addition to answer。感谢您在此处提供的深入回答。