生成器与迭代器
题目1: 生成器函数的语法是什么?如何使用 yield
?
答案: 生成器函数使用 function*
语法定义,使用 yield
关键字产生值:
javascript
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = numberGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
扩展: yield
可以接收值,这个值会作为上一次 next()
调用的返回值。
题目2: 什么是迭代器?如何手动实现一个迭代器?
答案: 迭代器是一个对象,它定义了一个 next()
方法,该方法返回一个包含 value
和 done
属性的对象。
手动实现迭代器:
javascript
function createIterator(array) {
let index = 0;
return {
next: function() {
if (index < array.length) {
return { value: array[index++], done: false };
} else {
return { done: true };
}
}
};
}
const it = createIterator([1, 2, 3]);
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()); // { done: true }
扩展: ES6 引入了 Symbol.iterator
,允许对象定义它们的迭代行为。
题目3: 如何使用生成器函数实现异步操作?
答案: 生成器函数可以用于实现异步操作,通常与 Promise 结合使用:
javascript
function* asyncGenerator() {
const result1 = yield fetch('https://api.example.com/data1');
console.log(result1);
const result2 = yield fetch('https://api.example.com/data2');
console.log(result2);
}
function run(generator) {
const iterator = generator();
function iterate(iteration) {
if (iteration.done) return Promise.resolve(iteration.value);
return Promise.resolve(iteration.value)
.then(x => iterate(iterator.next(x)));
}
return iterate(iterator.next());
}
run(asyncGenerator);
扩展: 这种模式是 async/await 的前身,现在通常直接使用 async/await。
题目4: 什么是可迭代对象?如何创建一个可迭代对象?
答案: 可迭代对象是实现了 Symbol.iterator
方法的对象。创建可迭代对象:
javascript
const iterableObject = {
[Symbol.iterator]: function* () {
yield 1;
yield 2;
yield 3;
}
};
for (const item of iterableObject) {
console.log(item); // 1, 2, 3
}
扩展: 数组、字符串、Map 和 Set 都是内置的可迭代对象。
题目5: 生成器函数和普通函数的区别是什么?
答案: 主要区别:
- 语法:生成器函数使用
function*
声明 - 执行:生成器函数返回一个生成器对象,而不是直接执行函数体
- 暂停和恢复:生成器函数可以使用
yield
暂停执行,并在之后恢复 - 状态保持:生成器函数可以在多次调用之间保持其内部状态
- 双向通信:可以通过
next()
方法向生成器传值,通过yield
从生成器获取值
扩展: 生成器函数特别适合于处理大量数据或无限序列,因为它们可以按需生成值,而不需要一次性将所有值存储在内存中。