Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从雄辩的javascript中解释此javascript函数_Javascript - Fatal编程技术网

从雄辩的javascript中解释此javascript函数

从雄辩的javascript中解释此javascript函数,javascript,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

我很难理解这个函数。我不明白变量
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));
好的,在看了一段时间后,我有几个问题可能会澄清一些事情:

1) 如果说每次调用find都会跟踪它自己的起始值,这是正确的说法吗?例如,当调用find(1)时,它的起始值为1,当调用find(1+5)时,find(1)的起始值仍然为1,但find(1+5)现在的起始值为6

2) 我很难跟踪stacktrace,即使我看到它打印出来。这就是我的看法:

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

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

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

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

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

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

这是我遇到的问题,如果find(21+5)和find(21*3)都返回null,它如何知道接下来调用find(16*3)。为什么它不能再次找到(16+5)


在find(16)调用find(21+5)和find(21*3)的地方,它是否有什么关系?因为它们在调用函数中返回null,所以它执行了| |语句的第二部分,即find(16*3)。

它是一个不同的变量。无论何时调用特定的find(x),其start值都不会影响start的任何其他实例

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

当调用find(6)时,它调用find(11),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)
find(6):
开始=6,历史=(1+5)
查找(6+5):
开始=11,历史=((1+5)+5)
查找(11+5):
开始=16,历史=((1+5)+5)+5)
... 继续等等。。。
查找(11*3):
开始=33,历史=((1+5)+5)*3)
查找(6*3):
开始=24,历史=((1+5)*3)

您没有考虑递归分支。它可能会出现上下抖动,但您只是到达一个递归树的底部并跳到另一个递归树

处理电话:


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

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



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

也许你还没有完全信服,但你已经明白了

关于问题1,可以正确地说,
start
值是沿着内部调用保留的。就像每个调用都有自己的“上下文”——即使修改了变量和参数值,这也不会传递到外部函数调用。这就是范围

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

所以我想你把一切都搞定了


我修改了原始脚本,所以它打印了一个调用跟踪。看到它在行动

这是一个局部跟踪,
start
的值在进一步移动后似乎“减小”到16:


该函数在16分支下更进一步,然后停止,返回到上面的调用,其中
start
为11。然后它继续为
开始
尝试11*3的值,然后再次停止,依此类推。

两个管道不是表示“或”吗?如何返回一个或另一个呢?@ScottC:in-Javascript,“或”
| |
如果第一项为true ish,则返回第一项;如果第一项为false ish,则返回第二项(包括null)。它是布尔or的泛化,其行为类似于空合并运算符。@ScottC:阅读Javascript书中有关布尔条件的章节。这与
var x=y | | z;返回x@ScottC:你应该买本书。你不能通过谷歌来学习编程。@ScottC:当然,但要小心其中许多是不正确的/不完整的/误导性的。:)我同意,find的新实例包含start和history的新实例,也许javascript没有传递变量ByVal,而是有一种传递ByRef的方法??像C++一样?如果这正是您想要实现的,那么所述函数是正确的。Xaisoft似乎认为find只有一个上下文(有多个)。与“findSequence只有一个上下文,因此goal只有一个值”(这是真的)相比,它是一个深度优先搜索,在start>goal时停止,所以find(26)发生在find(24)之前,这就是Xaisoft所困惑的地方。@Jimmy:当
start>goal
时它不会停止,当
start==goal
时它会停止。当
start>goal
当前树被放弃,但其他树仍被搜索。是的,问题中的混乱是因为他认为start只有一个值。@Jimmy:是的,我已经演示了他看到的值——可能在“watch”窗口中——如何安全地上下变化,当烟囱树被清扫时。哦,好的
                        1
              6---------+----------3
        11----+--18          8-----+-----
     16-+-33  23-+--48    13-+--24
  21-+-80   28+69       18+39 
26+63                23+90
                    28+69