"return undefined" (JavaScript) 的递归问题

Recursion troubles with "return undefined" (JavaScript)

我被递归困住了。我读过一些类似的问题,但这并没有让我松一口气。 我的函数在内部运行良好,但它 returns 最后是“未定义”。

我有一个二叉树。现在我正在尝试制作一个函数,它可以给我一个答案:如果此级别上的任何节点具有 children.

class tree_node {
    constructor(n_array, parent) {
        this.n_array = n_array;
        this.has_children = false;
        this.children = [];
        if (parent != null) {
            this.parent = parent;
            this.level = this.parent.level + 1;
        }
        else {
            this.level = 0;
        }
        // run the tree
        this.child();
    }
    child() {
        if (this.n_array.length != 1) {
            this.has_children = true;
            let m = Math.floor(this.n_array.length / 2);
            let l = this.n_array.slice(0, m);
            let r = this.n_array.slice(m);
            const left = new tree_node(l, this);
            const right = new tree_node(r, this);
            this.children.push(left, right);
        }
        else return 0
    }

    get_if_node_has_children(node, level) {
        console.log(node.level, node.has_children)
        if (node.has_children && node.level < level) {
            console.log("in loop")
            node.children.forEach(element => {
                return element.get_if_node_has_children(element, level);
            });
        }
        else {
            console.log("first else")
            if (node.level == level && node.has_children) {
                console.log("node.level == level && node.has_children " + node.n_array)
                return true;
            }
            else {
                console.log("return false")
                return false;
            }
        }
    }
    show() {
        console.log(this.n_array + " | Level: " + this.level + ". " + this.branch + " Has children = " + this.has_children);
        if (this.has_children) {
            this.children.forEach(element => {
                return element.show();
            });
        }
        else {
            return 0;
        }
    }    
}

get_if_node_has_children(node, level) 可以这么说。我已经预料到了确切的行为和日志。除了事情:函数returns“未定义”。但是我不知道我错过了什么。

let root = [];

class tree_node {
  constructor(n_array, parent) {
    this.n_array = n_array;
    this.has_children = false;
    this.children = [];
    // при создании экземпляра класса то parent == null
    if (parent != null) {
      this.parent = parent;
      this.level = this.parent.level + 1;
    } else {
      this.level = 0;
    }
    // run the tree
    this.child();
  }
  child() {
    if (this.n_array.length != 1) {
      this.has_children = true;
      let m = Math.floor(this.n_array.length / 2);
      let l = this.n_array.slice(0, m);
      let r = this.n_array.slice(m);
      const left = new tree_node(l, this);
      const right = new tree_node(r, this);
      this.children.push(left, right);
    } else return 0
  }

  get_if_node_has_children(node, level) {
    console.log(node.level, node.has_children)

    if (node.has_children && node.level < level) {
      console.log("in loop")
      node.children.forEach(element => {
        return element.get_if_node_has_children(element, level);
      });
    } else {
      console.log("first else")
      if (node.level == level && node.has_children) {
        console.log("node.level == level && node.has_children " + node.n_array)
        return true;
      } else {
        console.log("return false")
        return false;
      }
    }
  }

  show() {
    console.log(this.n_array + " | Level: " + this.level + ". " + "Has children = " + this.has_children);
    if (this.has_children) {
      this.children.forEach(element => {
        return element.show();
      });
    } else {
      return 0;
    }
  }
  // CLASS END ===========================
}

root = new tree_node([1, 3, 5, 7, 9, ])
console.log("=== root.show() ===")
root.show();
console.log("=== let a = root.get_if_node_has_children(root, 2) ===")
let a = root.get_if_node_has_children(root, 2)
console.log(" a is " + a)

有两个问题:

  1. return 在回调中(例如,您的 forEach 回调)只是来自回调的 returns,而不是调用 forEach 的函数.通常,在现代代码中,除非需要元素的索引,否则使用 for-of

  2. 您在返回之前没有检查递归调用的结果。但是如果你在returnsfalse上调用它的第一个子节点,你想继续寻找,而不是立即返回false

修复两者:

get_if_node_has_children(node, level) {
    console.log(node.level, node.has_children)
    if (node.has_children && node.level < level) {
        console.log("in loop")
        for (const element of node.children) { // *** #1, using `for-of` instead of `forEach` so we can return below
            const hasChild = element.get_if_node_has_children(element, level);
            if (hasChild) {     // *** #2, only return here if you got `true`
                return true;    // *** 
            }                   // *** 
        }
        return false; // *** #2 part 2 -- didn't find it anywhere, return `false`
    } else {
        console.log("first else")
        if (node.level == level && node.has_children) {
            console.log("node.level == level && node.has_children " + node.n_array)
            return true;
        } else {
            console.log("return false")
            return false;
        }
    }
}

不过我会稍微重新组织一下,如果我删除一些 no-longer-needed 日志记录会更容易:

get_if_node_has_children(node, level) {
    console.log(node.level, node.has_children)
    if (node.has_children) {
        if (node.level === level) {
            return true;
        }
        if (node.level < level) {
            for (const element of node.children) {
                if (element.get_if_node_has_children(element, level)) {
                    return true;
                }
            }
        }
    }
    return false;
}