通过未知DOM

时间:2016-01-14 17:44:59

标签: javascript dom recursion

我正在学习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);

<!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>
&#13;
&#13;
&#13;

下一步是:

  1. 文档节点
  2. 我们与他的第一个孩子重复这个功能:头节点
  3. 我们与他的第一个孩子一起重复这个功能:元节点
  4. 因为&#39; meta&#39;没有孩子,我们重复他的下一个功能 兄弟姐妹:标题节点
  5. 因为&#39; title&#39;没有孩子或下一个兄弟,我们结束了 函数where node = title,我们应该结束node =的函数 meta,我们应该继续检查head的下一个兄弟: body node
  6. 而不是,如果你调试或检查控制台,你会看到浏览器重复该部分:

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

    其中node = meta,所以我们得到两个&#39; TITLE&#39;打印在控制台上。它应该已经消失了,我们得到了&#39;身体&#39;节点。同样的问题发生在&#39; LI&#39;元件。

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

    如果您在开发人员工具上进行调试,则会更容易理解。

3 个答案:

答案 0 :(得分: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
      ...

所以现在你明白为什么覆盖函数参数是不好的。

如果你想要一个更强大的方法,我将编写一个递归的DOM遍历函数:

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

  console.log(node.nodeName);

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

mostrarNodosV2(document);

这里唯一的区别是我检查节点有效性一次递归比每个节点更深,这降低了方法的详细程度。

答案 1 :(得分:3)

您正在重新分配node变量,请尝试以下操作:

function mostrarNodosV2(node) {
    console.log(node.nodeName);
    if (node.firstElementChild != null) {
        var child = node.firstElementChild;
        mostrarNodosV2(child);
    }
    if (node.nextElementSibling != null) {
        var sibling = node.nextElementSibling;
        mostrarNodosV2(sibling);
    }
}
mostrarNodosV2(document);

答案 2 :(得分:1)

没有必要实现自己的,TreeWalker DOM Level 2 API允许遍历,选择自定义起始节点并改变方向。