JavaScript高级程序设计笔记 7
第7章 迭代器与生成器 — 快速复习笔记
1. 迭代器(Iterator)
1.1 迭代器模式
- 提供一种方法顺序访问集合中的每个元素,无需暴露底层结构。
- JavaScript 中的迭代器是对象,必须实现
next()方法。 next()返回对象:{ value: any, done: boolean }value:当前元素的值done:是否迭代完成(true表示结束)
1.2 可迭代协议(Iterable Protocol)
- 要求对象实现
[Symbol.iterator]方法,该方法返回一个迭代器。 - 内置可迭代类型:
Array、String、Map、Set、arguments、NodeList等。 - 接收可迭代对象的语法:
for-of、...扩展运算符、Array.from()、解构赋值等。
// 手动获取迭代器
let arr = [1,2,3];
let it = arr[Symbol.iterator]();
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }
1.3 自定义可迭代对象
- 为对象添加
[Symbol.iterator]方法,返回带next()的对象。
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return {
next: () => {
if (this.current <= this.to) {
return { value: this.current++, done: false };
} else {
return { done: true };
}
}
};
}
};
for (let num of range) console.log(num); // 1 2 3 4 5
1.4 提前终止迭代器
- 可选的
return()方法:当迭代器提前退出时(如break、throw)调用。 - 用于释放资源(如关闭文件、清除定时器)。
2. 生成器(Generator)
2.1 基础概念
- 生成器是能返回生成器对象的函数,可以暂停和恢复执行。
- 定义:在
function关键字后加*(function* generatorFn())。 - 生成器对象既是迭代器也是可迭代对象。
2.2 yield 关键字
- 只能在生成器函数内部使用。
- 遇到
yield会暂停执行,并返回yield后的值(作为next().value)。 - 下一次调用
next()从上次暂停处继续执行。
function* gen() {
yield 1;
yield 2;
return 3; // 可选,done: true 时的 value
}
let g = gen();
console.log(g.next()); // { value: 1, done: false }
console.log(g.next()); // { value: 2, done: false }
console.log(g.next()); // { value: 3, done: true }
2.3 传参与 yield 表达式
next(param):参数会作为上一个yield表达式的返回值。- 第一个
next()的参数会被忽略(因为没有上一个yield)。
function* gen() {
let a = yield 'first';
console.log(a); // 接收第二次 next() 的参数
let b = yield 'second';
console.log(b);
}
let g = gen();
console.log(g.next()); // { value: 'first', done: false }
console.log(g.next(10)); // 10 赋值给 a,value: 'second'
console.log(g.next(20)); // 20 赋值给 b
2.4 yield*(委托生成器)
- 用于在生成器中调用另一个生成器(或可迭代对象),逐个产出值。
function* gen1() {
yield 1;
yield 2;
}
function* gen2() {
yield* gen1();
yield 3;
}
for (let v of gen2()) console.log(v); // 1 2 3
// 等价于 yield* [1,2] 或 yield* "ab"
2.5 提前终止生成器
return():强制生成器进入关闭状态,done: true,后续next()无效。throw():在生成器内部抛出错误,可被try-catch捕获。
function* gen() {
try {
yield 1;
yield 2;
} catch(e) {
console.log('error caught');
}
}
let g = gen();
console.log(g.next()); // { value: 1, done: false }
g.throw(new Error('boom')); // 输出 "error caught"
3. 内置可迭代 API
| 语法/API | 说明 |
|---|---|
for-of |
遍历可迭代对象 |
...(扩展运算符) |
将可迭代对象转为数组 |
Array.from() |
将可迭代对象转为数组 |
解构赋值 [a,b] = set |
从可迭代对象中取值 |
Map/Set 构造函数 |
可接收可迭代参数 |
Promise.all() / Promise.race() |
参数为可迭代对象 |
4. 应用场景
4.1 自定义迭代序列
- 如斐波那契数列生成器
function* fibonacci() {
let [prev, cur] = [0, 1];
while (true) {
yield cur;
[prev, cur] = [cur, prev + cur];
}
}
let f = fibonacci();
console.log(f.next().value); // 1
console.log(f.next().value); // 1
console.log(f.next().value); // 2
4.2 惰性求值
- 只在需要时计算下一个值,节省内存。
4.3 异步流程控制(ES6 时代)
- 配合 Promise 实现类似
async/await的效果(现已很少手动实现)。
5. 常见面试题速查
-
什么是可迭代对象?
→ 实现了[Symbol.iterator]方法的对象,该方法返回一个迭代器。 -
迭代器与可迭代对象的区别?
→ 可迭代对象提供迭代器(通过[Symbol.iterator]),迭代器是包含next()方法的对象。 -
如何判断一个对象是否可迭代?
→ 检查typeof obj[Symbol.iterator] === 'function'。 -
for-of与for-in的区别?
→for-of遍历可迭代对象的值;for-in遍历对象可枚举属性(包括原型链)。 -
生成器函数与普通函数的区别?
→ 生成器函数调用时返回生成器对象,不会立即执行;可暂停(yield)和恢复。 -
yield和return在生成器中的作用?
→yield暂停并返回值,return终止生成器并设置done: true。 -
yield*的作用是什么?
→ 将迭代控制委托给另一个可迭代对象或生成器,逐个产出值。 -
生成器如何接收外部传入的值?
→ 通过next(param),参数会成为上一个yield表达式的返回值。 -
如何提前终止生成器?
→ 调用return()或throw()。 -
生成器能否实现无限序列?
→ 可以,只要循环中没有结束条件,每次next()都会产生下一个值。

浙公网安备 33010602011771号