在递归函数中,Typescript break vs return行为

时间:2017-10-18 16:14:45

标签: javascript typescript recursion

以下是用于recursively walk a source file's abstract syntax tree (AST)的两个打字稿功能。我设法找出导致我的程序只访问部分树的问题,但我不明白为什么解决方案有效。

walkTree1函数是遍历整个树的有效解决方案。 walkTree2函数仅访问树的一部分。这两个函数只有一行(用注释标记),显然return行为以某种方式与此有关,但我没有在网上找到任何有用的东西。

function walkTree1(firstNode: ts.SourceFile, visitor: (node: ts.Node) => void): void {
  visitInterfacesRecursive(firstNode);

  function visitInterfacesRecursive(node: ts.Node): void {
    switch (node.kind) {
      case ts.SyntaxKind.InterfaceDeclaration:
        visitor(node); break; // correct
      default:
        ts.forEachChild(node, visitInterfacesRecursive);
    }
  }
}

function walkTree2(firstNode: ts.SourceFile, visitor: (node: ts.Node) => void): void {
  visitInterfacesRecursive(firstNode);

  function visitInterfacesRecursive(node: ts.Node): void {
    switch (node.kind) {
      case ts.SyntaxKind.InterfaceDeclaration:
        return visitor(node); // offending change
      default:
        ts.forEachChild(node, visitInterfacesRecursive);
    }
  }
}

最后,我很难过。我觉得我在这里遗漏了一些明显的东西。我已经检查了生成的源,并且似乎没有任何意外(除了类型擦除之外没有真正的区别)。现在我发布原始代码;如果有必要的话,我会在以后回家的时候把更可重复的东西放在一起。

其他详情:

2 个答案:

答案 0 :(得分:2)

更改的唯一区别是让visitInterfacesRecursive返回调用visitor(node)的结果(在walkTree2中),而在walkTree1 visitInterfacesRecursive中可靠地返回undefined。*

无论调用visitInterfacesRecursive是什么,都清楚地看到它的回报值。在walkTree1中,该返回值可靠undefined。在walkTree2中,有时undefined,有时visitor(node)返回。看来visitor(node)会返回除undefined以外的内容(至少有时会),而且无论是visitInterfacesRecursive的返回值,都会解释非undefined返回值意思是"停止。"

*"可靠地返回undefined" - 从技术上讲,ECMAScript规范区分了一个根本不使用return的函数和一个使用returnreturn undefined的函数,但它所做的区别是不可观察的在我们的代码中。调用该函数在所有三种情况下都会得到相同的结果。

答案 1 :(得分:2)

这是因为在所有情况下ts.forEachChild()实际上并没有在每个孩子身上跑过。来自链接的source

// Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
// stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
// embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
// a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.

因此,既然你要回归visitor(node),那么它有时必须是真实的。即使您已将visitor()声明为void - 返回函数,这可能会在运行时发生,我猜? (您已经忽略了您使用的特定visitor(),因此我不确定)因为您不关心visitor()它的返回值最好不要从visitInterfacesRecursive()返回。

希望有所帮助;祝你好运!