DOM 的深度优先遍历和广度优先遍历

DOM 树

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<div class="root">
  <div class="container">
    <section class="sidebar">
      <ul class="menu"></ul>
    </section>
    <section class="main">
      <article class="post"></article>
      <p class="copyright"></p>
    </section>
  </div>
</div>

深度优先

结果:[root, container, sidebar, menu, main, post, copyright]

递归方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const arr = [];
function traversalDFSDOM (rootDom) {
  if (!rootDom) return;
  if (rootDom.children.length === 0) { // 叶子节点
    arr.push(rootDom);
    return;
  }
  arr.push(rootDom); // 非孩子节点,每次遍历孩子节点之前需要 push 到数组中
  for (let i = 0; i < rootDom.children.lenght; i++) {
    traversalDFSDOM(rootDom.children[i]);
  }
}

非递归

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const arr = [];
function traversalDFSDOM (rootDom) {
  if (!rootDom) return;
  const stack = [];
  let node = rootDom;
  while (node !== null) {
    arr.push(node);
    if (node.children.length >= 0) {
      for (let i = node.children.length - 1; i >= 0; i--) {
        stack.unshift(node.children[i]);
      }
      node = stack.shift();
    }
  }
}

广度优先

结果:[root, container, sidebar, main, menu, post, copyright]

递归方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
const stack = [rootDom];
function traversalBFSDOM (count) {
  count = count | 0;
  if (stack[count]) {
    let children = stack[count].children;
    for (let i = 0; i < children.length; i++) {
      stack.push(children[i]);
    }
    traversalBFSDOM(++count);
  }
}

非递归

先进先出的思想

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const arr = [];
function traversalDFSDOM (rootDom) {
  if (!rootDom) return;
  arr.push(rootDom);
  const queue = [rootDom];
  while (queue.length) {
    let node = queue.shift();
    if (!node.children.length) {
      continue;
    }
    for (let i = 0; i < node.children.length; i++) {
      arr.push(node.children[i]);
      queue.push(node.children[i]);
    }
  }
}