从Eloquent Javascript解释这个javascript函数

Xai*_*oft 5 javascript

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

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));
Run Code Online (Sandbox Code Playgroud)

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

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).

Hum*_*rto 6

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

关于问题1,说这些start值是在内部调用中保留的,这是正确的.这就像每个调用都有自己的"上下文" - 即使你修改变量和参数值,这也不会被带到外部函数调用.这是范围.

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

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


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

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

在此输入图像描述

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


Jim*_*mmy 2

这是一个不同的变量。每当调用特定的 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 和 start * 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)
Run Code Online (Sandbox Code Playgroud)