javascript - Recursive function for going through unknown DOM - Stack Overflow

admin2025-04-19  0

I am learning about js DOM and I want to make a recursive function that I could use to go through all nodes in any DOM. I made it, but I can not figure out why my first attempt is not working:

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>

I am learning about js DOM and I want to make a recursive function that I could use to go through all nodes in any DOM. I made it, but I can not figure out why my first attempt is not working:

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>

The flow is next:

  1. document node.
  2. we repeat the function with his first child: head node.
  3. we repeat the function with his first child: meta node.
  4. because of 'meta' has no childs, we repeat the function with his next sibling: title node.
  5. because of 'title' has no childs or next sibling, we end the function where node=title, we should end the function where node = meta, and we should continue checking the next sibling of head: body node.

Instead of that, if you debug or check the console you will see that browser repeats the section:

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

Where node = meta, and so we get two 'TITLE' printed on console. Then it goes as it should have gone, and we get the 'body' node. The same problem happens with the 'LI' element.

So, I do not want another solution, I just did it, I just want to know why I go back to that 'if', because I don't get it.

If you debug it on developer tools it would be easier to understand.

Share Improve this question edited Jan 14, 2016 at 17:49 Lee Taylor 7,99416 gold badges37 silver badges53 bronze badges asked Jan 14, 2016 at 17:44 OrnitierOrnitier 1711 gold badge1 silver badge6 bronze badges 5
  • 1 I did it -> [].slice.call( document.querySelectorAll('*') ).forEach( ... – adeneo Commented Jan 14, 2016 at 17:51
  • @adeneo that's not the point, the point is to debug the recursive function OP already has. – Patrick Roberts Commented Jan 14, 2016 at 19:02
  • @PatrickRoberts which is why it was a ment not an answer, and relevant. – David Barker Commented Jan 14, 2016 at 19:21
  • @DavidBarker not really. This question is tagged recursion whereas adeneo's snippet is iterative. – Patrick Roberts Commented Jan 14, 2016 at 19:35
  • @PatrickRoberts Yet somehow it is still not an answer, and it is still relevant to the question. – David Barker Commented Jan 14, 2016 at 19:36
Add a ment  | 

3 Answers 3

Reset to default 4

The reason why your recursive function repeated nodes was because you reassigned node. Let's step through the function ourselves:

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
      ...

So now you understand why it's bad to overwrite the function argument.

If you would like a more robust approach, here is how I would have written a recursive DOM traversal function:

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

  console.log(node.nodeName);

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

mostrarNodosV2(document);

The only difference here is I'm checking the node validity one recursion deeper than you were for each node, which reduces the verbosity of your approach.

you are re-assigning node variable, try this:

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);

There is no need to implement your own, the TreeWalker DOM Level 2 API allows traversal, choosing a custom start node and changing the direction.

转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1745062566a282788.html

最新回复(0)