迭代器与生成器
ES6(ECMAScript 2015)引入了迭代器(Iterators)和生成器(Generators),为 JavaScript 提供了更强大的控制流功能,特别是在处理循环和异步编程方面。它们使得代码更加简洁、直观,并提高了可读性和维护性。
迭代器
迭代器是一种对象,它定义了一个序列的值(或键值对)的获取方式,并跟踪当前遍历的指针位置。在 ES6 中,任何实现了Iterator协议的对象都可以被称为迭代器。该协议要求实现一个名为next()的方法,此方法返回一个包含value和done两个属性的对象。
- 创建一个简单的迭代器:
javascript
function makeIterator(array) {
let index = 0;
return {
next: function () {
if (index < array.length) {
return { value: array[index++], done: false };
} else {
return { value: undefined, done: true };
}
},
};
}
let it = makeIterator(["a", "b", "c"]);
console.log(it.next()); // 输出: { value: "a", done: false }
console.log(it.next()); // 输出: { value: "b", done: false }
console.log(it.next()); // 输出: { value: "c", done: false }
console.log(it.next()); // 输出: { value: undefined, done: true }可迭代对象
为了使对象成为可迭代对象,需要实现[Symbol.iterator]方法,该方法返回一个迭代器。
- 创建一个自定义的可迭代对象:
javascript
let myIterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
},
};
for (let value of myIterable) {
console.log(value); // 输出: 1, 2, 3
}生成器
生成器函数是使用function*语法声明的特殊函数,它可以暂停执行并稍后恢复,每次执行到yield语句时都会暂停。生成器非常适合用于复杂的控制流逻辑,比如异步流程控制。
- 基本生成器函数示例:
javascript
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
let gen = generatorFunction();
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 }使用生成器进行异步操作
生成器可以与 Promises 结合使用来简化异步代码的编写。虽然这在现代 JavaScript 中更多地被async/await所替代,但在某些情况下,生成器仍然非常有用。
- 结合 Promise 使用生成器模拟
async/await:
javascript
function asyncFunction() {
return new Promise((resolve) => {
setTimeout(() => resolve("完成"), 1000);
});
}
function* main() {
const result = yield asyncFunction(); // 暂停直到Promise解决
console.log(result); // 输出: 完成
}
function execute(generator) {
const iterator = generator();
function handle(iteratorResult) {
if (!iteratorResult.done) {
iteratorResult.value.then(
(res) => handle(iterator.next(res)),
(err) => iterator.throw(err)
);
}
}
handle(iterator.next());
}
execute(main);通过这些新特性,ES6 大大增强了 JavaScript 处理复杂数据结构和控制流的能力,特别是对于异步编程的支持,使得代码更加简洁和易于理解。