推荐答案
迭代器 (Iterator)
迭代器是一种对象,它允许你以某种方式遍历一个集合(例如数组、对象、Map、Set等)。它遵循特定的协议,主要包含一个 next() 方法。每次调用 next() 方法都会返回一个包含 value 和 done 属性的对象。value 代表当前迭代的值,done 是一个布尔值,表示迭代是否完成。当 done 为 true 时,表示迭代已经结束,不再有新的值。
// www.javascriptcn.com code example
const myIterator = {
items: [1, 2, 3],
index: 0,
next: function() {
if (this.index < this.items.length) {
return { value: this.items[this.index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
console.log(myIterator.next()); // {value: 1, done: false}
console.log(myIterator.next()); // {value: 2, done: false}
console.log(myIterator.next()); // {value: 3, done: false}
console.log(myIterator.next()); // {value: undefined, done: true}生成器 (Generator)
生成器是一种特殊的函数,使用 function* 语法声明。生成器函数执行时不会立即运行,而是返回一个迭代器对象。生成器函数内部可以使用 yield 关键字来暂停执行,并返回一个值。每次调用迭代器的 next() 方法时,生成器函数会从上次 yield 处恢复执行,直到再次遇到 yield 或者函数结束。生成器可以创建无限序列,以及处理异步操作。
// www.javascriptcn.com code example
function* myGenerator() {
yield 1;
yield 2;
yield 3;
}
const generator = myGenerator();
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}
function* fibonacciGenerator() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacciGenerator();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3本题详细解读
迭代器 (Iterator) 详解
迭代器协议
迭代器协议定义了如何生成一个序列的值。它是一个对象,需要实现一个 next() 方法。这个 next() 方法返回的对象必须包含两个属性:
value: 迭代的当前值。done: 一个布尔值,表示迭代是否完成。当为true时,表明没有更多值可以迭代了。
可迭代对象 (Iterable)
一个对象如果拥有一个名为 [Symbol.iterator] 的方法,并且这个方法返回一个符合迭代器协议的对象,那么它就是一个可迭代对象。JavaScript 中一些内置的数据结构,例如 Array, Map, Set 和 String 都是可迭代对象。
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}使用场景
for...of循环:for...of循环可以直接遍历可迭代对象。- 展开语法 (...): 可以将可迭代对象展开为数组或函数参数。
- 解构赋值: 可以使用解构语法从可迭代对象中提取值。
- 自定义迭代: 当你需要自定义数据结构的遍历方式时,可以实现自定义的迭代器。
生成器 (Generator) 详解
生成器函数
生成器函数使用 function* 语法定义,它并非立即执行,而是返回一个生成器对象。
// www.javascriptcn.com code example
function* myGenerator() {
console.log('start');
yield 1;
console.log('after 1');
yield 2;
console.log('after 2');
yield 3;
console.log('end');
}
const gen = myGenerator();
console.log('before next');
gen.next(); // start
// after 1
console.log('next 1');
gen.next(); // after 2
// next 2
gen.next(); // end
console.log('next 3');
yield 关键字
yield 关键字用于暂停生成器函数的执行,并返回一个值。每次调用生成器对象的 next() 方法时,生成器函数会从上次 yield 语句处恢复执行,直到遇到下一个 yield 或者函数结束。
yield* 关键字
yield* 关键字可以委托另一个生成器或可迭代对象。
// www.javascriptcn.com code example
function* anotherGenerator() {
yield 'a';
yield 'b';
}
function* mainGenerator() {
yield 1;
yield* anotherGenerator();
yield 2;
}
const gen = mainGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: undefined, done: true }使用场景
- 生成无限序列: 由于生成器函数可以暂停和恢复执行,因此可以用于生成无限序列的值。
- 处理异步操作: 可以结合
async/await来处理异步操作,使得异步代码看起来更像是同步代码。 - 状态机: 可以实现状态机,根据不同的状态生成不同的值。
- 惰性求值: 生成器只在需要的时候才计算值,可以节省资源。
生成器与迭代器的关系
生成器函数返回一个迭代器,因此生成器天然就是一个迭代器。 它使用 yield 提供 value ,并且通过内部逻辑控制 done 属性。 生成器让开发者更容易定义迭代行为,无需手动创建迭代器。