iterator 暴露需兼顾封装性与可用性:应通过命名导出的生成器函数或只读视图提供受控迭代能力,避免泄露内部结构、跨模块耦合或异步副作用,并确保返回非空有效迭代器。

在模块化重构中,Iterator 的暴露不是简单返回一个 Symbol.iterator 方法,而是要结合模块边界、封装意图与消费方契约来设计——既要提供可迭代能力,又不能破坏模块内聚性或泄露内部数据结构。
明确迭代目的,按需暴露只读视图
模块不应直接导出原始数组或 Map 实例,否则调用方可能意外修改状态。应返回封装后的可迭代对象,例如:
- 用
function* items()生成器函数封装遍历逻辑,控制输出内容(如过滤敏感字段) - 返回
Object.freeze([...data])的浅拷贝数组,再通过for...of消费,避免副作用 - 若使用 TypeScript,可定义
Iterable<publicitem></publicitem>类型,确保类型层面不暴露私有属性
通过模块导出接口统一管理迭代入口
在 module-info.java 级别虽不直接约束 JS,但在 JS 模块化(如 ES Module)中,应将迭代能力收敛到命名导出项中:
- 导出
listCourses()而非courses数组本身 - 该函数返回
IterableIterator<coursesummary></coursesummary>,其中CourseSummary是精简 DTO,不含课程详情或关联用户数据 - 模块的
package.json中设置"exports"字段,仅允许访问./iterators子路径,屏蔽底层实现
配合模块依赖策略隔离迭代逻辑
当课程模块依赖用户模块时,课程迭代器不应直接 yield 用户完整对象,而应:
- 只暴露用户 ID 或摘要(如
{ id: 'u123', name: '张老师' }),由消费方按需调用用户模块的getUserById()获取详情 - 在迭代器内部避免跨模块调用耗时操作(如数据库查询),确保每次
next()是同步、轻量的 - 若需异步迭代(如分页加载),显式使用
AsyncIterator并导出async function* fetchAllCourses(),让调用方清楚感知异步边界
避免常见陷阱:可选链与空值合并不适用于 Iterator 初始化
?. 和 ?? 解决的是属性访问安全问题,但 Iterator 对象本身不能为 null 或 undefined 后再调用 [Symbol.iterator]。正确做法是:
- 模块方法始终返回有效迭代器(哪怕空集合也返回
function* () {}) - 消费方无需判空即可写
for (const item of module.listItems()) { ... } - 若数据源可能不存在,应在模块层抛出语义化错误(如
new DataUnavailableError()),而非返回undefined
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











