1

I have this basic code to handle all text nodes:

function walk (node) {
    if (node.nodeType == '3') {
        handleText (node)
    }
    node = node.firstChild
    while (node) {
        walk (node)
        node = node.nextSibling
    }
}

Unfortunately, this handles all text nodes, including elements such as <script> and <style>, which I do not want. I updated to my code to the following to ignore these specific elements:

function walk (node) {
    if (node.nodeType == '3' && node.tagName != 'SCRIPT' && node.tagName != 'STYLE') {
        handleText (node)
    }
    node = node.firstChild
    while (node) {
        walk (node)
        node = node.nextSibling
    }
}

However, this is not working. What am I doing wrong?

2 Answers2

1

The tag check should be on the parent node :

function walk(node) {
  if (node.nodeType == 3 && !/SCRIPT|STYLE/.test(node.parentNode.tagName)) handleText(node);
    
  for (node = node.firstChild; node; node = node.nextSibling) walk(node)
}
Slai
  • 22,144
  • 5
  • 45
  • 53
0

A node with a nodeType of 3 will be a text node. Since it sounds like you want to exclude the traversal of text nodes which are children of script or style tags, you should put the test elsewhere - only walk(node) if tagName is not SCRIPT OR STYLE, so that the parent <script> / <style> tag is not iterated over in the first place:

function walk (node) {
  if (node.nodeType === 3) {
    handleText (node);
  }
  node = node.firstChild;
  while (node) {
    const { tagName } = node;
    if (tagName !== 'SCRIPT' && tagName !== 'STYLE') {
      walk (node);
    }
    node = node.nextSibling;
  }
}

(also note that nodeType evaluates to an integer, so you can use strict equality comparison === instead)

To avoid a while loop and reassignment, you might consider using forEach instead:

function walk (node) {
  if (node.nodeType === 3) {
    handleText (node);
    return;
  }
  Array.prototype.forEach.call(
    node.childNodes,
    (childNode) => { 
      const { tagName } = childNode;
      if (tagName !== 'SCRIPT' && tagName !== 'STYLE') {
        walk (child);
      }
    }
  );
}
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Thank you for your help! I noticed you gave an alternative example to "avoid a `while` loop and reassignment." Is using "a `while` loop and reassignment" bad to do? – Kaden Campbell Feb 09 '19 at 01:46
  • It's a bit opinion-based, but arguably, yes. Code is easier to read when nothing gets reassigned - manually reassigning an *outer* variable at the *end* of a loop is harder to make sense of at a glance. Loops in general are better avoided in most cases; array methods provide more abstraction, are composable, and don't require manual iteration or reassignment. – CertainPerformance Feb 09 '19 at 01:51