要让类支持自定义遍历,需实现可迭代协议:JavaScript用[Symbol.iterator]()返回生成器,Python分Iterable与Iterator两层设计,PHP优选IteratorAggregate+Generator;遍历逻辑须解耦、惰性求值、状态隔离。

要让一个类支持自定义遍历规则,关键不是直接让它“变成迭代器”,而是让它成为可迭代对象(Iterable),即实现迭代器协议——在 JavaScript 中是 [Symbol.iterator]() 方法,在 Python 中是 __iter__() 方法,在 PHP 中是实现 IteratorAggregate 或返回 Traversable。这个方法不自己遍历,而是每次调用时**返回一个新的、独立的迭代器实例**。
JavaScript:用 Symbol.iterator 返回生成器或手动迭代器
最简洁的方式是用生成器函数,它天然返回符合协议的迭代器:
- 在类中定义
[Symbol.iterator]() { return this.#generate(); } - 私有方法
#generate使用function*,内部用yield按需产出值 - 例如遍历树结构时,可 yield 当前节点值,再递归
yield*子节点 - 若需控制状态(如跳过空节点、按深度优先/广度优先切换),把逻辑写在生成器内,而非类属性上
Python:分离 Iterable 和 Iterator 类
不能让同一个对象既被多次 for 循环又保持状态。正确做法是两层设计:
-
MyData类只实现__iter__(self),每次返回MyDataIterator(self.data) -
MyDataIterator类持有遍历状态(如self.index或self.stack),只实现__next__和__iter__(返回自身) - 这样每次
for x in obj:都获得全新迭代器,互不影响 - 若需支持反向遍历,可额外提供
__reversed__方法
PHP:优先用 IteratorAggregate + Generator
比起手动实现全部五个 Iterator 方法,更推荐组合使用:
- 类实现
IteratorAggregate接口,只写一个getIterator()方法 - 该方法内直接
return $this->yieldItems();,其中yieldItems()是带yield的生成器方法 - 生成器自动处理
current/next等状态,你只需专注“怎么取下一个值” - 如需支持嵌套结构,生成器中可用
yield from $child->getIterator();委托子对象
通用要点:遍历逻辑应与数据解耦
自定义遍历规则的本质,是把“如何访问元素”的决策权从 for 循环里收回来。所以:
- 避免在类中用
public $position记录全局遍历状态 - 不要在
__iter__或[Symbol.iterator]中直接遍历并返回数组——那会失去惰性求值优势 - 如果规则依赖参数(如“只遍历偶数层级”“跳过 null 值”),把这些参数传给迭代器构造函数,而不是传给
__iter__ - 对无限或大体积数据,务必用生成器;对需多次重放的场景,确保每次
__iter__都新建迭代器

















