DFS一条路走到黑再回退,BFS一圈圈向外铺开;DFS递归实现前序遍历,需判空children;BFS用队列按层处理,适合懒加载等场景。

JavaScript 中的深度遍历(DFS)和广度遍历(BFS)本质是两种访问树或图结构节点的策略,核心区别在于“访问顺序”:DFS 一条路走到黑再回退,BFS 一圈圈向外铺开。实际开发中,它们常用于 DOM 遍历、树形组件渲染、菜单展开、路径查找等场景。
深度优先遍历(DFS)——递归写法最直观
适合层级不深、逻辑清晰的结构。先处理当前节点,再递归处理每个子节点(类似树的前序遍历):
- 函数接收一个节点(如
node),先将其加入结果数组 - 遍历
node.children,对每个子节点递归调用自身 - DOM 场景下注意判断
node.children是否存在且长度大于 0,避免报错
示例代码:
function dfs(node) {const result = [];
if (!node) return result;
result.push(node);
for (let i = 0; i result.push(...dfs(node.children[i]));
}
return result;
}
深度优先遍历(DFS)——非递归写法更可控
用栈(Stack)模拟递归过程,避免深层嵌套导致的栈溢出。关键点是“后进先出”,所以子节点要倒序入栈,才能保证从左到右访问:
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 初始化一个栈,把根节点压入
- 循环:弹出栈顶节点 → 记录 → 将其子节点**从右往左**依次压入栈
- DOM 中可用
Array.prototype.push()和.pop()实现栈
示例代码:
function dfsIterative(root) {if (!root) return [];
const stack = [root];
const result = [];
while (stack.length) {
const node = stack.pop();
result.push(node);
if (node.children && node.children.length) {
// 倒序压入,确保左子树先被处理
for (let i = node.children.length - 1; i >= 0; i--) {
stack.push(node.children[i]);
}
}
}
return result;
}
广度优先遍历(BFS)——队列驱动,天然按层处理
适合需要“逐层操作”的场景,比如找 DOM 中第 N 层的所有 input 元素、实现树形控件的懒加载展开。核心是“先进先出”:
- 初始化一个队列(用数组模拟),根节点入队
- 循环:队首出队 → 记录 → 其所有子节点依次入队尾
- DOM 中推荐用
.push()入队、.shift()出队;若性能敏感,可用deque或双指针优化
示例代码:
function bfs(root) {if (!root) return [];
const queue = [root];
const result = [];
while (queue.length) {
const node = queue.shift();
result.push(node);
if (node.children && node.children.length) {
for (let i = 0; i queue.push(node.children[i]);
}
}
}
return result;
}
实际应用小贴士
DOM 遍历时需注意:children 只返回元素节点(Element),不包括文本或注释节点;若需所有子节点,改用 childNodes 并手动过滤;另外,现代项目中可结合 querySelectorAll 或 TreeWalker 实现更灵活的遍历,但 DFS/BFS 仍是理解底层逻辑的基础。

















