JavaScript进阶①|迭代器与生成器,手写可迭代对象
·
author: 专注前端开发,分享JavaScript干货
title: JavaScript进阶①|迭代器与生成器,手写可迭代对象
update: 2026-04-28
tags: JavaScript,迭代器,生成器,Iterator,Generator,Symbol.iterator,前端进阶
作者:专注前端开发,分享JavaScript干货
更新时间:2026年4月
适合人群:掌握ES6基础,想深入理解迭代机制的开发者
前言:迭代器是什么?
迭代器(Iterator) 是一种接口,定义了如何遍历一个对象。
生成器(Generator) 是创建迭代器的特殊函数,用 function* 和 yield 实现。
一、可迭代对象(Iterable)
// 可迭代对象:实现了 [Symbol.iterator] 方法的对象
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
// 内置可迭代对象
console.log(arr[Symbol.iterator]); // Function
console.log("hello"[Symbol.iterator]); // Function
console.log(new Set()[Symbol.iterator]); // Function
console.log(new Map()[Symbol.iterator]); // Function
// 普通对象默认不可迭代
const obj = { a: 1, b: 2 };
// console.log(obj[Symbol.iterator]); // undefined ❌
二、手写可迭代对象
// 让对象变成可迭代的
const myObj = {
data: [10, 20, 30],
// 实现 [Symbol.iterator] 方法
[Symbol.iterator]() {
let index = 0;
const data = this.data;
return {
next() {
if (index < data.length) {
return { value: data[index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
// 现在可以用 for...of 遍历了
for (const item of myObj) {
console.log(item); // 10, 20, 30
}
// 也可以用 spread 操作符
console.log([...myObj]); // [10, 20, 30]
三、生成器(Generator)基础
// 生成器函数:function* 定义
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
// 调用生成器函数,返回迭代器
const gen = myGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
// 生成器是可迭代的(实现了 [Symbol.iterator])
for (const value of myGenerator()) {
console.log(value); // 1, 2, 3
}
四、生成器的高级用法
4.1 yield 传值
function* gen() {
const x = yield 10; // 第一个 next() 返回 10
console.log("x =", x); // x = 20(第二个 next 传入的值)
const y = yield x * 2; // 第二个 next 返回 20*2=40
console.log("y =", y); // y = 30
return x + y; // 最终返回值
}
const g = gen();
console.log(g.next()); // { value: 10, done: false }
console.log(g.next(20)); // x 被赋值为 20,返回 { value: 40, done: false }
console.log(g.next(30)); // y 被赋值为 30,返回 { value: 50, done: true }
4.2 yield* 委托
function* inner() {
yield "a";
yield "b";
return "inner done";
}
function* outer() {
yield "开始";
const result = yield* inner(); // 委托给 inner,接收其 return 值
console.log(result); // "inner done"
yield "结束";
}
for (const v of outer()) {
console.log(v); // "开始", "a", "b", "结束"
}
4.3 生成器实现异步(早期的 async/await)
// 用生成器模拟 async/await
function* fetchData() {
const user = yield fetch("https://jsonplaceholder.typicode.com/users/1");
console.log("用户:", user);
const posts = yield fetch("https://jsonplaceholder.typicode.com/posts?userId=1");
console.log("帖子:", posts);
return { user, posts };
}
// 运行生成器的辅助函数
function runGenerator(gen) {
const iterator = gen();
function handle(result) {
if (result.done) return result.value;
// 假设 yield 后面跟的是 Promise
return result.value.then(data => {
return handle(iterator.next(data));
});
}
return handle(iterator.next());
}
runGenerator(fetchData);
五、实战:自定义范围迭代器
// 创建一个可迭代的范围对象
function createRange(start, end, step = 1) {
return {
[Symbol.iterator]() {
let current = start;
return {
next() {
if ((step > 0 && current < end) || (step < 0 && current > end)) {
const value = current;
current += step;
return { value, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
}
// 使用
for (const num of createRange(0, 10, 2)) {
console.log(num); // 0, 2, 4, 6, 8
}
console.log([...createRange(5, 0, -1)]); // [5, 4, 3, 2, 1]
六、实战:异步任务队列(Generator版)
// 用生成器实现异步任务队列
function* taskQueue() {
console.log("任务1开始");
yield new Promise(resolve => setTimeout(() => {
console.log("任务1完成");
resolve();
}, 1000));
console.log("任务2开始");
yield new Promise(resolve => setTimeout(() => {
console.log("任务2完成");
resolve();
}, 1000));
console.log("任务3开始");
yield new Promise(resolve => setTimeout(() => {
console.log("任务3完成");
resolve();
}, 1000));
return "所有任务完成";
}
// 运行队列
function runQueue(gen) {
const it = gen();
function iterate(iteration) {
if (iteration.done) {
console.log(iteration.value);
return;
}
const promise = iteration.value;
promise.then(() => {
iterate(it.next());
});
}
iterate(it.next());
}
runQueue(taskQueue);
// 输出:任务1开始 → 任务1完成 → 任务2开始 → 任务2完成 → ...
七、知识卡
| 概念 | 说明 |
|---|---|
Symbol.iterator |
使对象可迭代 |
next() |
返回 { value, done } |
function* |
定义生成器函数 |
yield |
暂停并返回值 |
yield* |
委托给另一个可迭代对象 |
for...of |
遍历可迭代对象 |
... |
展开可迭代对象 |
八、课后作业
- 手写一个
range(1, 10)可迭代对象,用for...of遍历输出 1-10 - 用生成器实现一个斐波那契数列生成器,调用
next()依次返回 0, 1, 1, 2, 3, 5… - 实现一个
take(gen, n)函数,从生成器中取前 n 个值
有问题欢迎评论区留言,大家一起讨论!
标签:JavaScript | 迭代器 | 生成器 | Iterator | Generator | Symbol.iterator | 前端进阶
更多推荐
所有评论(0)