闭包使迭代器游标变量私有持久化,避免循环变量共享错误;用let或IIFE为每次迭代创建独立作用域,createIterator通过闭包封装index实现状态化迭代。

闭包在迭代器函数中维持游标指针,核心是让游标变量(如 index)脱离循环作用域,被内部返回的函数长期持有——也就是通过闭包“捕获”并私有化这个状态。
用闭包封装游标变量,避免循环变量污染
常见错误是在 for 或 forEach 中直接返回函数,却共享同一个变量:
// ❌ 错误:所有回调共享同一个 i,执行时 i 已为 arr.length
const arr = ['a', 'b', 'c'];
const iterators = [];
for (var i = 0; i < arr.length; i++) {
iterators.push(() => arr[i]); // i 是全局/函数作用域变量
}
console.log(iterators[0]()); // undefined(i === 3)
✅ 正确做法:用立即执行函数或 let 声明,为每次迭代创建独立作用域:
- 用
let(推荐):块级作用域保证每次循环的i独立 - 用 IIFE(兼容旧环境):把当前
i作为参数传入,形成闭包绑定
实现一个带游标的状态化迭代器
真正的迭代器需要可多次调用、按需前进。闭包让游标 index 成为私有且持久的状态:
立即学习“Java免费学习笔记(深入)”;
function createIterator(arr) {
let index = 0; // 游标定义在外部函数作用域内
return function() {
if (index < arr.length) {
return { value: arr[index++], done: false };
} else {
return { value: undefined, done: true };
}
};
}
<p>const next = createIterator(['x', 'y', 'z']);
console.log(next()); // { value: 'x', done: false }
console.log(next()); // { value: 'y', done: false }
console.log(next()); // { value: 'z', done: false }
console.log(next()); // { value: undefined, done: true }
这里 index 不会被外部访问,也不会被重置——每次调用 next() 都操作同一个闭包内的 index,自然维持了游标位置。
与 ES6 迭代器协议结合(Symbol.iterator)
更标准的做法是返回符合迭代器协议的对象,其 next() 方法仍靠闭包维持状态:
function arrayIterator(arr) {
let index = 0;
return {
next() {
if (index < arr.length) {
return { value: arr[index++], done: false };
}
return { done: true };
},
[Symbol.iterator]() { return this; } // 支持 for...of
};
}
<p>const it = arrayIterator(['p', 'q']);
console.log(it.next()); // { value: 'p', done: false }
for (const item of it) console.log(item); // 'q'
注意:index 依然在闭包中,即使 it 被传到别处、被多次遍历(只要没重新调用 arrayIterator),游标状态就持续有效。
实际应用:分页加载、懒计算、状态机
闭包维持游标不只是为了“数数”,而是支撑有状态的按需行为:
- 分页迭代器:游标是页码 + 当前页内偏移,闭包封装整个分页逻辑
- 生成器模拟(无
yield时):用闭包保存中间计算状态,比如斐波那契迭代器 - 事件流控制:每次调用返回下一个预设事件,游标指向事件队列中的位置
关键不是“怎么存”,而是“谁有权读写”——闭包把游标变成仅由迭代函数控制的私有字段,不依赖外部变量或 this 绑定,干净可靠。


















