繁体   English   中英

从Eloquent Javascript解释这个javascript函数

[英]Explain this javascript function from Eloquent Javascript

我很难跟上这个功能。 我不明白的变量是如何start恢复到16达到26的值大于24后。

function findSequence(goal) {
  function find(start, history) {
    if (start == goal)
      return history;
    else if (start > goal)
      return null;
    else
      return find(start + 5, "(" + history + " + 5)") ||
             find(start * 3, "(" + history + " * 3)");
  }
  return find(1, "1");
}

print(findSequence(24));

好的,在看了一段时间后,我有几个问题可能会澄清一些事情:

1)说每个查找调用都跟踪它自己的起始值是否是正确的陈述? 例如,当调用find(1)时,它的起始值为1,当调用find(1 + 5)时,find(1)的起始值仍为1,但find(1 + 5)现在具有它的起始值为6。

2)即使我看到它打印出来,我也很难跟踪堆栈跟踪。 这就是我查看它的方式:

find(1)调用find(1 + 5)// start = 1

find(6)调用find(6 + 5)// start = 6,Passes

find(11)调用find(11 + 5)// start = 11,Passes

find(16)调用find(16 + 5)// start = 16,Passes

find(21)调用find(21 + 5)// start = 21,失败

因为find(21 + 5)返回null,所以它尝试调用find(21 * 3),它也返回null。

这是我遇到的部分,如果发现(21 + 5)和找到(21 * 3)返回null,接下来如何调用find(16 * 3)。 为什么不再找(16 + 5)?

在find(16)中调用find(21 + 5)和find(21 * 3)并且因为那些返回null到调用函数时,它有什么可做的,它执行了||的第二部分 找到的陈述(16 * 3)。

也许你并不完全相信,但你明白了。

关于议题1,它是正确的说, start值沿着内来电保存。 这就像每个调用都有自己的“上下文” - 即使你修改变量和参数值,这也不会被带到外部函数调用。 这是范围。

问题2似乎与短路布尔评估有关。 行为正如您所描述的那样:一旦表达式位于||左侧 运算符返回“truey”,右边的表达式将不会被评估。 反之亦然:如果左表达式为“falsey”,则解释器将继续评估正确的表达式。 结果值将是第一个非假名值,或链中的最后一个值。

所以我认为你得到了一切!


我修改了原始脚本,因此它打印了一个调用跟踪。 这里看到它。

这是一个部分跟踪,其中start值在进一步显示后“减少”为16:

在此输入图像描述

该函数在16分支下稍微进一步,然后它停止,恢复到上部调用,其中start为11.然后它继续尝试11 * 3的值start ,然后它再次停止,依此类推。

这是一个不同的变量。 只要调用特定的find(x),它的start值就不会影响start的任何其他实例。

当调用find(21)时,它返回null,因为find(26)和find(63)同样返回null,find(16)和find(11)返回null

当调用find(6)时,它调用find(11),返回null,因此它接下来调用find(24)。 在此调用的上下文中,start == 6,因此它继续start + 5并开始* 3。

find(6):
start = 6, history = (1 + 5)
     find(6 + 5):
     start = 11, history = ((1 + 5) + 5)
         find(11 + 5):
         start = 16, history = (((1 + 5) + 5) + 5)
         ... continued etc...

         find(11 * 3):
         start = 33, history = (((1 + 5) + 5) * 3)
         <end>
     find(6 * 3):
     start = 24, history = ((1 + 5) * 3)

你不是在考虑递归分支。 看起来似乎开始上下抖动,但你只是到达一个递归树的底部并跳到另一个递归树。

通过电话:


递归树中的start值( start+5 / start*3上的分支):

                        1
              6---------+----------3
        11----+--18          8-----+-----
     16-+-33  23-+--48    13-+--24
  21-+-80   28+69       18+39 
26+63                23+90
                    28+69

当值过高时,查看每个分支如何结束,然后当处理向右跳转到下一个分支start ,您看到的start值会下降。 找到'24'时处理停止。


(免责声明:我还没有完全检查所有的数学,但原则应该是合理的!)

暂无
暂无

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

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