遍历DOM的最快方式(广度优先)

时间:2012-10-30 23:57:46

标签: javascript jquery dom traversal

对不起,如果这听起来像是一个奇怪的需要。

用户可以按任意顺序创建包含任意数量元素的HTML页面,Div将被分配一个类。我无法控制它们的订单或位置。

我需要遍历DOM并使用特定于我的框架的类名称在每个div上调用init函数。所以我不知道他们将被安排的顺序。

以下是我的挑战: - 我正在使用递归的.children()Jquery调用然后遍历当前元素的每个子元素......我想我需要找到一种更快的方法来实现这一点,这是一个性能损失。 - 迭代时,$ .each()比循环标准更快。我不知道为什么。 $ .each()对较小的集合执行得更快吗? (即大小<20)

我的另一种选择是在每个类上做一个选择器,但我需要做几次迭代,因为这不能保证顺序,所以迭代会抵消任何性能优势。

所以我的需求: - 首先遍历DOM广度的更好表现方式。如果我能找到比JQuery函数更好的性能,那么简单的'Javascript就好了。

对不起,我知道这听起来有点奇怪。非常欢迎任何建议。

3 个答案:

答案 0 :(得分:1)

首先,你不应该受到巨大的打击。问题可能在您的代码中的其他地方,但您没有向我们展示您目前拥有的内容,因此我无从谈论。也就是说,这是一个应该非常快速的想法:

var classes = ["class1", "class2", "class3"];
i = classes.length, divs, j, curDiv;

while(i--) {
    divs = document.getElementsByClassName(classes[i]);
    j = divs.length;

    while(j--) {
        var curDiv = divs[j];
        // call some init function on the current div
    } 
}

如果这不是很快,你必须在其他地方遇到问题(同样,不要忘记确保在文档加载后调用它)。


至于$.each()是否比标准for循环更快,这几乎是一个经验法则:本机代码比库代码更快(但库代码通常更方便)。在这种情况下也是如此;您的平均for循环将比$.each()快得多。

答案 1 :(得分:1)

对于广度优先的树遍历...

const 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>`;

const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");

function BFT_dom(root) {

    const queue = [];
    let currentEl = root;

    while(currentEl) {
      console.log(currentEl) // Do something to element here

      for(let i = 0; i < currentEl.children.length; i++) {
          queue.push(currentEl.children[i]);
      }
      currentEl = queue.shift();
  }

}

BFT_dom(doc)

答案 2 :(得分:0)

使用当前的语法,这里的内容会更简洁一些。

    function bfs(root) {
      const queue = [];
      while (root) {
        console.log(root);
        [...root.children].forEach(child => queue.push(child));
        root = queue.shift();
      }
    }

    bfs(document.body);
    <html>
      <head>
        <title>Breadth First</title>
      </head>

      <body>
        <div class="a">
          <div class="aa">
            <span class="aaa"></span>
            <span class="aab"></span>
          </div>
        </div>
        <div class="ab">
          <span class="aba"></span>
          <span class="abb"></span>
        </div>
        <script src="main.js"></script>
      </body>
    </html>