通过未知DOM的递归函数

Orn*_*ier 5 javascript recursion dom

我正在学习js DOM,我想创建一个递归函数,我可以用它来遍历任何DOM中的所有节点.我做到了,但我无法弄清楚为什么我的第一次尝试不起作用:

HTML

function mostrarNodosV2(node) {
  console.log(node.nodeName);
  if (node.firstElementChild != null) {
    node = node.firstElementChild;
    mostrarNodosV2(node);
  }

  if (node.nextElementSibling != null) {
    node = node.nextElementSibling;
    mostrarNodosV2(node);
  }

}

mostrarNodosV2(document);
Run Code Online (Sandbox Code Playgroud)
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Exercise IV</title>
</head>

<body>
  <h1> Just a header</h1>
  <p>Nice paragraph</p>
  <ul>
    <li>Im just an element list on an unordered list</li>
  </ul>
</body>

</html>
Run Code Online (Sandbox Code Playgroud)

流程如下:

  1. 文档节点.
  2. 我们用他的第一个孩子重复这个功能:头节点.
  3. 我们用他的第一个孩子重复这个功能:元节点.
  4. 因为'meta'没有孩子,我们用他的下一个兄弟节点重复这个功能:标题节点.
  5. 因为'title'没有子节点或下一个兄弟节点,我们结束node = title的函数,我们应该结束node = meta的函数,我们应该继续检查head:body节点的下一个兄弟节点.

而不是那样,如果您调试或检查控制台,您将看到浏览器重复该部分:

if (node.nextElementSibling != null) {
    node = node.nextElementSibling;
    mostrarNodosV2 (node);
}
Run Code Online (Sandbox Code Playgroud)

其中node = meta,所以我们在控制台上打印了两个'TITLE'.它应该已经消失了,我们得到了'body'节点."LI"元素也会出现同样的问题.

所以,我不想要另一个解决方案,我只是想做,我只是想知道为什么我会回到'如果',因为我没有得到它.

如果您在开发人员工具上调试它会更容易理解.

Pat*_*rts 4

您的递归函数重复节点的原因是因为您重新分配了node. 让我们自己单步执行该函数:

document -> has a child
  html -> has a child
    head -> has a child
      meta -> has no child, has a sibling
        title -> has no child or sibling
    head -> head has been overwritten with meta, which has a sibling
      title -> has no child or sibling
  html -> html has been overwritten with head, which has a sibling
    body -> has a child
      h1 -> has no child, has a sibling
        p -> has no child, has a sibling
          ul -> has a child
            li -> has no child or sibling
          ul -> ul has been overwritten with li, which has no sibling
    body -> body has been overwritten with h1, which has a sibling
      ...
Run Code Online (Sandbox Code Playgroud)

现在您明白为什么覆盖函数参数是不好的了。

如果您想要一种更健壮的方法,我将按照以下方式编写递归 DOM 遍历函数:

function mostrarNodosV2(node) {
  if (node == null) {
    return;
  }

  console.log(node.nodeName);

  mostrarNodosV2(node.firstElementChild);
  mostrarNodosV2(node.nextElementSibling);
}

mostrarNodosV2(document);
Run Code Online (Sandbox Code Playgroud)

这里唯一的区别是我对每个节点检查的节点有效性比您更深的递归,这减少了方法的冗长。