javascript中树形结构可通过symbol.iterator接口支持for...of遍历,按深度优先顺序逐个返回节点;核心是用栈模拟递归或生成器函数yield*委托子迭代器实现dfs遍历。

JavaScript 中通过实现 Symbol.iterator 接口,可以让树形结构支持原生 for...of 遍历,并按深度优先顺序(DFS)逐个返回节点。核心是用栈模拟递归过程,在迭代器的 next() 方法中维护状态,避免一次性展开全部节点。
树节点类需定义迭代器接口
每个节点应返回一个迭代器对象,该对象具备 next() 方法和 [Symbol.iterator]() 方法。通常让节点自身可迭代,返回一个闭包封装的迭代器逻辑:
- 构造函数中不预计算所有子节点值,只保存引用
-
[Symbol.iterator]返回一个生成器函数或手动实现的迭代器对象 - 推荐用生成器函数(
function*)写法,语义清晰、自动管理状态
用生成器函数实现 DFS 迭代器
生成器天然适合描述深度优先遍历流程:先返回当前节点,再递归 yield 子树。注意 yield* 可委托子迭代器,保持扁平化输出:
class TreeNode {
constructor(value, children = []) {
this.value = value;
this.children = children;
}
<p><em>[Symbol.iterator]() {
yield this.value;
for (const child of this.children) {
yield</em> child; // 递归委托,等价于 for (const v of child) yield v
}
}
}</p>
这样写后,for (const val of root) {...} 就能按根→左→右的 DFS 顺序访问所有值。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
手动实现迭代器(无生成器时)
若需兼容旧环境或精细控制栈行为,可手动维护一个栈数组,每次 next() 弹出栈顶节点,将其子节点逆序压入(保证左子树先被处理):
- 初始化时将根节点放入栈
-
next()中取出栈顶,返回其值;再把它的子节点从右到左推入栈 - 栈为空时返回
{ done: true }
示例:
[Symbol.iterator]() {
const stack = [this];
return {
next() {
if (stack.length === 0) return { done: true };
const node = stack.pop();
// 逆序压入,使第一个子节点最后入栈、最先出栈
for (let i = node.children.length - 1; i >= 0; i--) {
stack.push(node.children[i]);
}
return { value: node.value, done: false };
}
};
}
支持多种遍历策略的扩展方式
可通过工厂方法返回不同遍历逻辑的迭代器,例如:
-
dfsIterator():深度优先(默认) -
bfsIterator():广度优先(用队列代替栈) -
preOrderIterator()、postOrderIterator():显式区分遍历时机
这样既保持接口统一,又便于按需选择策略,不影响 for...of 的使用方式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










