当前位置: 首页 > 知识库问答 >
问题:

Javascript-ONLY DOM Tree Traversal - DFS and BFS?

吴哲
2023-03-14

任何人都可以提供代码,伪代码,甚至提供良好的链接来实现DFS(深度优先搜索)和BFS(广度优先搜索)在普通JavaScript(没有JQuery,或任何帮助程序库)中?我一直在试图了解如何实现任一遍历,但我似乎无法真正区分 BFS 和 DFS 实现的区别。

如果我们想要一个具体问题作为示例:我想在给定节点上遍历 DOM,并获取所有类名。

(我认为遍历的唯一方法是遍历每个父节点,从该节点获取我需要的东西,在本例中是类名,然后查看它们是否有子节点,递归每个子节点。我相信这是DFS?同样,我很难理解DOM遍历实现中的差异!)

最后,如果这是一个重复,很抱歉。我到处寻找好的、清晰的例子,但没有找到任何好的答案!如果已经有好的答案,请告诉我:)

共有3个答案

元彦君
2023-03-14

对于DFS,您可以使用TreeWalker或NodeIterator API并使用NodeFilter.SHOW_ELEMENT进行过滤。

卞安邦
2023-03-14

DFS:

function m(elem) {
    elem.childNodes.forEach(function(a) {
        m(a);
    });
    //do sth with elem
}
m(document.body);

这将循环遍历所有元素,并对每个元素遍历每个子元素,依此类推。

基础设施:

var childs = [];

function m(elem) {
    elem.childNodes.forEach(function(a) {
        childs.push(a);
    });
    b = childs;
    childs = [];
    b.forEach(function(a) {
        m(a);
    });
}
m(document.body);

这将循环元素,将其子元素推到堆栈上,然后从每个元素开始。正如您所看到的,这会消耗更多的空间(子数组),这不是最好的。。。

韩鸿
2023-03-14

让我们使用以下 HTML 代码作为示例:

<div class="a">
    <div class="aa">
        <span class="aaa">
        </span>
        <span class="aab">
        </span>
    </div>
    <div class="ab">
        <span class="aba">
        </span>
        <span class="abb">
        </span>
    </div>
</div>

DFS 将始终首先转到下一级节点,并且仅当不再有未遍历的子节点时,它才会单步执行到当前级别的下一个节点。

DFS将按以下顺序遍历示例的节点:

a, aa, aaa, aab, ab, aba, abb

BFS 将始终首先遍历当前级别中的所有节点,然后才会进入下一级节点。

BFS将按以下顺序遍历示例中的节点:

a, aa, ab, aaa, aab, aba, abb

没有一个明确的答案,你应该使用其中的哪一个。通常这取决于你的需要。

实施细节:

对于DFS,人们经常使用堆栈。

伪代码:

stack my_stack;
list visited_nodes;
my_stack.push(starting_node);

while my_stack.length > 0
   current_node = my_stack.pop();

   if current_node == null
       continue;
   if current_node in visited_nodes
      continue;
   visited_nodes.add(current_node);

   // visit node, get the class or whatever you need

   foreach child in current_node.children
      my_stack.push(child);

此代码将一直持续到堆栈中有任何节点为止。在每个步骤中,我们都会获得堆栈中的顶级节点,如果它不为 null,并且我们以前没有访问过它,那么我们就会访问它并将其所有子节点添加到堆栈中。

队列通常用于BFS。

伪代码:

queue my_queue;
list visited_nodes;
my_queue.enqueue(starting_node);

while my_queue.length > 0
   current_node = my_queue.dequeue();

   if current_node == null
       continue;
   if current_node in visited_nodes
      continue;
   visited_nodes.add(current_node);

   // visit node, get the class or whatever you need

   foreach child in current_node.children
      my_queue.enqueue(child);

此代码将一直持续到队列中有任何节点。在每个步骤中,我们都会获得队列中的第一个节点,如果它不为空并且我们以前没有访问过它,那么我们将访问它并将其所有子节点添加到队列中。

请注意,这两种算法之间的主要区别是我们使用的数据类型。

 类似资料:
  • script是一小段程序,可以为您的网站添加交互性。 例如,脚本可以生成弹出警报框消息,或提供下拉菜单。 可以使用JavaScript或VBScript编写此脚本。 您可以使用任何脚本语言编写各种小函数,称为事件处理程序,然后您可以使用HTML属性触发这些函数。 现在,大多数Web开发人员只JavaScript和相关框架,甚至各种主流浏览器都不支持VBScript。 您可以将JavaScript代

  • 在本章中,我们将研究JavaScript 。 在Foundation中设置JavaScript很容易; 你唯一需要的就是jQuery。 JavaScript安装 您可以使用ZIP下载,包管理器或CDN来获取Foundation JavaScript文件。 在您的代码中,您可以提供指向jQuery和Foundation的链接作为标记,放在结束之前,并检查在jQuery之后加载Foundation。

  • 使用Java 8,Nashorn,引入了一个大大改进的javascript引擎,以取代现有的Rhino。 Nashorn提供2到10倍的性能,因为它直接编译内存中的代码并将字节码传递给JVM。 Nashorn使用Java 7中引入的调用动态特性来提高性能。 jjs 对于Nashorn引擎,JAVA 8引入了一个新的命令行工具jjs,用于在控制台执行javascript代码。 解释js文件 在c:\

  • js 代码如下 报错日志: ReferenceError: escodegen is not defined

  • 在本章中,我们将重点介绍在PyCharm编辑器中使用JavaScript的主要功能。 当用户通过URL实现JavaScript库时,PyCharm打算下载本地副本,以便可以用于完成和代码分析。 考虑我们的HTML文件的示例代码,如下所示,我们在上一章中创建了该代码 - 对于每个HTML文件或JavaScript文件,您可以检查通过PyCharm Editor的Settings配置加载的外部库。 观

  • 描述 (Description) 也可以使用相关的 app 方法使用 JavaScript 打开和关闭 popover,如下所示 - myApp.popover(popover, target) - 用于打开目标元素周围的myApp.popover(popover, target) ,它接受以下参数 - popover - 这是一个required参数,它是一个要打开的popover的HTMLEl

  • 描述 (Description) 您可以使用JavaScript App方法启用和禁用sortable,如下所示 - myApp.sortableOpen(sortableContainer) - 用于在指定的可排序容器上启用排序模式。 myApp.sortableClose(sortableContainer) - 用于在指定的可排序容器上禁用排序模式。 myApp.sortableToggle

  • 描述 (Description) 您可以使用JavaScript代码打开和关闭选取器模式。 您可以使用pickerModal(picker)方法打开closeModal(picker)模式和closeModal(picker)方法来关闭closeModal(picker)模式。 例子 (Example) 以下示例使用Framework7中的JavaScript显示打开和关闭选择器模式 - <!DO