"红宝书" 通常指的是《JavaScript 高级程序设计》,这是一本由 Nicholas C. Zakas(尼古拉斯·扎卡斯)编写的 JavaScript 书籍,是一本广受欢迎的经典之作。这本书是一部翔实的工具书,满满的都是 JavaScript 知识和实用技术。
不管你有没有刷过红宝书,如果现在还没掌握好,那就一起来刷红宝书吧,go!go!go!
系列文章:
第一部分:基本知识(重点、反复阅读)
第二部分:进阶内容
第 7 章 迭代器与生成器
ES6 规范新增了 2 个高级特性:迭代器和生成器
。
迭代器模式
JavaScript 中的迭代器是一种设计模式
,它提供了一种遍历容器(如数组、字符串或其他可迭代对象)的方法。
- 迭代器是一个可以
由任意对象实现的接口
,支持连续获取对象产出的每一个值。 - 任何实现 Iterable 接口的对象都有一个
Symbol.iterator 属性
,这个属性引用默认迭代器。 - 默认迭代器就像一个迭代器工厂,也就是一个函数,调用之后会产生一个实现 Iterator 接口的对象。
- 迭代器必须通过连续调用
next()
方法才能连续取的值,这个方法返回一个 IteratorObject。 - 这个对象包含一个
done 属性
和一个value 属性
。 - done 是一个布尔值,表示是否还有更多值可以访问。
- value 包含迭代器返回的当前值。
- 这个接口可以通过手动反复调用 next() 方法来消费,也可以通过原生消费者,比如 for-of 循环来自动消费。
js
// 迭代器对象
class Iterator {
constructor(collection) {
this.collection = collection;
this.index = 0;
}
// 获取下一个元素
next() {
if (this.index < this.collection.length) {
return { value: this.collection[this.index++], done: false };
} else {
return { done: true };
}
}
}
// 可迭代对象
class Iterable {
constructor(collection) {
this.collection = collection;
}
// 获取迭代器对象
getIterator() {
return new Iterator(this.collection);
}
}
// 使用迭代器遍历集合
const array = [1, 2, 3, 4, 5];
const iterable = new Iterable(array);
const iterator = iterable.getIterator();
while (true) {
const { value, done } = iterator.next();
if (done) break;
console.log(value);
}
- 迭代器在
处理大量数据
时非常有用,可以按需生成数据,而不必一次性加载整个集合。 - 可以通过迭代器
实现自定义数据结构的遍历
。
生成器
在 JavaScript 中,生成器(Generator)是一种特殊类型的函数,它允许你在需要时暂停和恢复函数的执行。生成器函数使用 function*
关键字进行定义,并包含一个或多个使用 yield
语句产生值的区块。生成器提供了一种更灵活的控制流,特别适用于异步编程。
- 生成器是一种
特殊的函数
,调用之后会返回一个生成器对象
。 - 生成器对象实现了 Iterable 接口,因此可用在任何消费可迭代对象的地方。
- 生成器的独特之处在于支持
yield
关键字,这个关键字能暂停执行生成器函数。 - 使用 yield 关键字还可以通过
next()
方法接受输入和产生输出。 - 在加上
星号
之后,yield 关键字可以将跟它后边的可迭代对象序列化为一连串值。
js
// 定义生成器函数
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
// 调用生成器函数不会执行函数体,而是返回一个生成器对象。
// 可以通过调用生成器对象的 `next()` 方法来启动或恢复生成器的执行。
let 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 }
// 生成器与 Promise 一起使用,可以实现更具可读性和易维护性的异步代码。
// async/await 就是生成器的语法糖
function* asyncGenerator() {
try {
const result = yield fetchData(); // fetchData 返回一个 Promise
console.log(result);
} catch (error) {
console.error(error);
}
}
async function runAsyncGenerator() {
const gen = asyncGenerator();
const { value, done } = await gen.next();
if (!done) {
// 处理异步结果
}
}
未完待续...
参考资料
《JavaScript 高级程序设计》(第 4 版)