JavaScript中Iterator通过Generator实现按需过滤迭代,避免预生成全部结果,适用于复杂表格数据的惰性处理、链式筛选及异步条件判断。

JavaScript 中的 Iterator 可以在复杂表格数据处理中实现按需过滤迭代,核心在于**不预先生成全部结果,而是每次调用 next() 时动态计算下一个满足条件的项**。这特别适合处理行数多、列结构嵌套、条件组合复杂或需链式筛选的表格数据(如带分组、展开行、合并单元格逻辑的二维数组或对象数组)。
用 Generator 函数封装表格行级过滤逻辑
将表格数据(例如 rows 数组)和过滤规则封装进一个 generator,每 yield 一个通过校验的行,天然支持“按需”:
- 避免一次性遍历全部数据,尤其当只需前 N 条匹配结果时(如分页加载首屏)
- 可组合多个过滤器:每个 generator 只关注单一职责(如
filterByStatus、searchByText),再用yield*链式委托 - 支持异步条件(配合
async function*+await,适用于需查 API 判断某行是否有效的场景)
示例(同步过滤):
function* filterRows(rows, predicate) {
for (const row of rows) {
if (predicate(row)) yield row;
}
}
<p>// 复杂条件:状态为 active,且 name 包含关键词,且关联的 tags 至少有一个是 'urgent'
const filtered = filterRows(tableData, row =>
row.status === 'active' &&
row.name?.includes(searchTerm) &&
Array.isArray(row.tags) && row.tags.some(t => t === 'urgent')
);
为嵌套结构(如树形表格、分组表)定制 Iterator
真实表格常含父子行(展开/折叠)、分组头、汇总行等。此时不能简单遍历原始数组,而需用 Iterator 按“渲染顺序”扁平化并过滤:
立即学习“Java免费学习笔记(深入)”;
- generator 内部递归遍历树节点,对每个节点(包括 group header、data row、footer)执行过滤判断
- 过滤函数可接收上下文(如当前层级、父 group 名),实现“仅显示某分组下的匹配子项”
- 返回的 iterator 仍保持惰性 —— 调用
next()才深入下一层,跳过整棵不匹配的子树
示例(树形表格):
function* traverseAndFilter(node, predicate, depth = 0) {
// 先检查当前节点自身是否符合(如 group header 也可被搜索)
if (predicate(node, { depth, type: 'node' })) {
yield node;
}
<p>// 若是父节点且有 children,再递归
if (Array.isArray(node.children)) {
for (const child of node.children) {
yield* traverseAndFilter(child, predicate, depth + 1);
}
}
}
结合 Symbol.iterator 实现可复用的可迭代类
把表格数据与过滤策略封装成类,让其实例直接支持 for...of 和扩展运算符,提升可读性和复用性:
- 类内部保存原始数据和过滤器列表;
[Symbol.iterator]返回一个 generator,依次应用各过滤器 - 支持链式调用:
new TableIterator(data).filter(...).search(...).limit(10),每个方法返回新实例(不可变) - 最终 iterator 只在首次
for...of或展开时启动,中间步骤无实际计算
关键片段:
class TableIterator {
constructor(data) {
this.data = data;
this.filters = [];
}
<p>filter(fn) {
const clone = new TableIterator(this.data);
clone.filters = [...this.filters, fn];
return clone;
}</p><p><em>[Symbol.iterator]() {
let items = this.data;
for (const fn of this.filters) {
items = filterRows(items, fn); // 复用前面定义的 generator
}
yield</em> items;
}
}</p><p>// 使用
for (const row of new TableIterator(allRows)
.filter(r => r.type === 'user')
.filter(r => r.score > 80)
.filter(r => r.tags?.includes('vip'))) {
renderRow(row);
}
注意边界:惰性 ≠ 无开销,需避免重复计算
Iterator 的按需特性不等于零成本。以下情况需主动优化:
- 若过滤函数本身耗时(如正则全局匹配、深对象遍历),考虑提前缓存结果或用 Memoize 工具
- 多次遍历同一 iterator 会重新执行全部逻辑(generator 不可重入),如需多次使用,应转为数组或用
Array.from(it)快照 - 与 UI 同步时(如 React 中 map 渲染),确保 key 稳定 —— 过滤后行序可能变化,避免用索引作 key
不复杂但容易忽略


















