When it comes to JavaScript, inline code (like in the 2nd example) is typically faster than using callbacks (as seen in the 1st example). This is because there is a significant overhead for a function call in JavaScript.
Therefore, the treeWalker method with callbacks may not be as fast as directly coded methods like in your 2nd example.
A similar situation applies when comparing a direct iteration of an array using a 'for' loop versus using the '.forEach()' method for the same array. Callback functions tend to slow down execution.
Although code with callback functions can be more versatile and sometimes shorter, it may not necessarily execute faster.
This lack of surprising speed improvement in callback functions is due to the process involved in calling a function in JavaScript. It requires name lookup, creating a new function context, passing parameters, creating local variables, executing the code, and cleaning up afterwards among other steps. The inline code version bypasses many of these steps.
To optimize both approaches, you can place tags in an object rather than an array:
var noGlobalTags = {"LI": true, "UL": true};
You can then check if a specific tag is in that list using code like:
noGlobalTags[node.tagName] // first example
or
if (noGlobalTags[node.childNodes[i].tagName]) // second example
This type of lookup should be much faster than the array search currently being used.
Below is a non-recursive version that also utilizes the quicker noGlobalTags lookup:
function getTextNodes(top) {
var queue = [], index, item, node;
queue.unshift({nodes: [top], pos: 0});
while (queue.length) {
item = queue[0];
index = item.pos++;
if (index < item.nodes.length) {
node = item.nodes[index];
if (node.nodeType == 3) {
textNodeEmoteParser(node);
} else {
if (node.childNodes.length && !noGlobalTags[node.tagName]) {
queue.unshift({nodes: node.childNodes, pos: 0});
}
}
} else {
queue.shift();
}
}
}
Update: this method is nearly 100 times faster. Another more efficient method that walks the tree directly has been discovered:
function customIterativeTreeWalker(root) {
var node = root.firstChild;
while (node != null) {
if (node.nodeType == 3) {
textNodeEmoteParser(node);
}
if (node.hasChildNodes()) {
if (node.tagName && noGlobalTags[node.tagName]) {
node = node.nextSibling;
} else {
node = node.firstChild;
}
} else {
while (node.nextSibling == null) {
node = node.parentNode;
if (node == root) {
return;
}
}
node = node.nextSibling;
}
}
}
Link to JSPerf comparison: http://jsperf.com/get-text-nodes-non-recursive/3