我正在学习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;
下一步是:
而不是,如果你调试或检查控制台,你会看到浏览器重复该部分:
if (node.nextElementSibling != null) {
node = node.nextElementSibling;
mostrarNodosV2 (node);
}
&#13;
其中node = meta,所以我们得到两个&#39; TITLE&#39;打印在控制台上。它应该已经消失了,我们得到了&#39;身体&#39;节点。同样的问题发生在&#39; LI&#39;元件。
所以,我不想要另一个解决方案,我只是想做,我只是想知道为什么我会回到那个&#39;如果&#39;因为我没有得到它。
如果您在开发人员工具上进行调试,则会更容易理解。
答案 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允许遍历,选择自定义起始节点并改变方向。