这是重读红宝书(JavaScript高级程序设计 第4版)的第9篇文章,本节我们来看看代理:迭代器、生成器、它们的本质是什么、实际有哪些应用
本节涉及源码见仓库 github.com/adamswan/Re…
1、迭代器
Iterable,词根 Iter 来自拉丁语,翻译为“重复”
迭代器就是原型上有 Symbol.iterator 属性,属性值是一个函数,该函数就是迭代器工厂函数,返回值是一个指针对象,通过指针对象上的 .next() 方法就可以访问当前数据结构的每一项,因此就能拿来做遍历。
.next()方法返回的迭代器对象 IteratorResult 包含两个属性:done 和 value。
幸运的是,我们不需要手动调用迭代器工厂函数,for...of、扩展操作符等会自动调用函数,你可以将 for...of、扩展操作符 理解为:它们都是迭代器的语法糖。
很多内置类型都实现了 Iterable 接口:字符串、数组、Map、Set 等,但普通对象(字面量{})没有Iterable 接口。
为何有迭代器?以上数据结构的遍历方式各不相同,迭代器提供了一种统一的方式来遍历各种数据结构,使得代码更加通用和可复用。
// 自定义一个迭代器对象
function createIterator(items) {
let index = 0;
return {
next: function () {
const done = index >= items.length;
const value = done ? undefined : items[index++];
return {
value,
done,
};
},
};
}
// 使用迭代器遍历数组
const arr = [1, 2, 3];
const iterator = createIterator(arr);
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 }
2、生成器
生成器是一种特殊的函数,它可以暂停和恢复执行。
生成器函数使用function*语法定义,在函数内部可以使用 yield 关键字暂停执行并返回一个值。
调用生成器并不会执行函数体,而是返回一个迭代器,使用迭代器的 next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或函数结束。
async、await 的底层其实是生成器
// 定义一个生成器函数
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
// 创建生成器对象
const generator = generatorFunction();
// 使用生成器对象进行迭代
console.log(generator.next()); // { value: 1, done: false }
console.log(generator.next()); // { value: 2, done: false }
console.log(generator.next()); // { value: 3, done: false }
console.log(generator.next()); // { value: undefined, done: true }
// 生成器可以直接用于 for...of 循环
for (const value of generatorFunction()) {
console.log(value); // 依次输出 1, 2, 3
}