可以自定义数组遍历逻辑,通过重写[Symbol.iterator]为生成器函数实现;例如跳过偶数索引元素:arr[Symbol.iterator] = function*() { for (let i = 1; i < this.length; i += 2) yield this[i]; }。

JavaScript 中可以用生成器函数(Generator Function)来自定义数组的遍历逻辑,核心是让数组的 [Symbol.iterator] 方法返回一个自定义的迭代器对象,而这个对象的 next() 方法由生成器函数控制。
让数组拥有自定义遍历行为
原生数组的遍历方式(如 for...of、扩展运算符、解构)都依赖其 [Symbol.iterator] 方法。我们可以重写这个方法,让它返回一个生成器函数执行后得到的迭代器。
例如,实现一个“跳过偶数索引元素”的遍历:
const arr = [10, 20, 30, 40, 50];
arr[Symbol.iterator] = function* () {
for (let i = 1; i < this.length; i += 2) { // 从索引 1 开始,每次+2 → 只取奇数位置
yield this[i];
}
};
<p>// 使用
for (const item of arr) {
console.log(item); // 输出:20, 40
}
封装可复用的自定义遍历类(带参数)
直接改写原生数组的 [Symbol.iterator] 不推荐(污染原型、影响其他代码)。更安全的做法是创建一个包装对象,在构造时传入数组和遍历规则。
立即学习“Java免费学习笔记(深入)”;
比如实现「反向遍历」或「步长遍历」:
class CustomArray {
constructor(arr, iterateFn) {
this.arr = arr;
this.iterateFn = iterateFn;
}
<p><em>[Symbol.iterator]() {
yield</em> this.iterateFn(this.arr);
}
}</p><p>// 反向遍历
const reversed = new CustomArray([1, 2, 3], arr =>
function* () {
for (let i = arr.length - 1; i >= 0; i--) yield arr[i];
}()
);</p><p>console.log([...reversed]); // [3, 2, 1]</p><p>// 每隔两个取一个(索引 0, 3, 6...)
const stepped = new CustomArray([1,2,3,4,5,6,7], arr =>
function* () {
for (let i = 0; i < arr.length; i += 3) yield arr[i];
}()
);
console.log([...stepped]); // [1, 4, 7]
利用生成器函数做惰性计算与条件过滤
生成器天然支持惰性求值,适合处理大数组或需要动态判断是否产出的场景(比如只遍历满足某条件的元素,且不提前构建新数组)。
- 避免一次性
filter().map()创建中间数组 - 每调用一次
next()才计算下一个匹配项 - 可配合
break提前终止,节省资源
function* evenSquares(arr) {
for (const x of arr) {
if (x % 2 === 0) yield x * x;
}
}
<p>const nums = [1, 2, 3, 4, 5, 6];
const iterator = evenSquares(nums);</p><p>console.log(iterator.next().value); // 4 (2²)
console.log(iterator.next().value); // 16(4²)
console.log(iterator.next().value); // 36(6²)
注意点与限制
生成器函数返回的是迭代器,不是数组,所以不能直接调用 .push()、.length 等方法。如需转为数组,用 [...iterator] 或 Array.from(iterator)。
- 生成器不可重复使用:一旦遍历完毕,再次
for...of将无输出,需重新调用生成器函数获取新迭代器 - 无法随机访问:只能按生成器定义的顺序逐个
next(),不支持arr[2]这种下标读取 - 错误处理建议在生成器内部用
try/catch,因为外部throw()会传入生成器暂停处


















