JS中,迭代器 是一个对象,它定义了一个 next() 方法,每次调用 next() 都会返回一个对象 { value, done },for...of、展开运算符 ...、Array.from() 等都依赖于迭代器,Array、Set、Map、String等数据结构都支持相同方式遍历,迭代器遍历时不会一次性加载所有数据,而是在next()执行后返回一个对象,通过value属性取出当前值,在遍历大数组时对内存压力较小。可迭代对象实现了 [Symbol.iterator]() 方法,该方法执行后返回一个迭代器。
基本使用
const set = new Set([10, 20, 30]);
// for...of循环遍历
for (const num of set) {
console.log(num); // 10, 20, 30
}
// 使用迭代器手动遍历
const iterator = set[Symbol.iterator]();
console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }
通过[Symbol.iterator]()方法来获取迭代器进行遍历,并且可以重写该方法自定义数据结构的遍历。
例如Object对象,可以通过手动实现[Symbol.iterator]()遍历
const obj = {
data1: 1,
data2: 2,
data3: 3,
[Symbol.iterator]() {
let index = 0;
const values = Object.values(this);
return {
next: () => {
return index < values.length
? { value: values[index++], done: false }
: { value: undefined ,done: true };
}
};
}
};
for (const num of obj) {
console.log(num); // 1, 2, 3
}
生成器
使用生成器函数创建可迭代对象不需要显式地维护其内部状态,使用function*编写,使用yield关键字返回值,具有可暂停、可返回值的特点。
function* generator() {
console.log("开始执行");
yield 1; // 暂停,返回 1
console.log("恢复执行");
yield 2; // 暂停,返回 2
console.log("再次恢复执行");
yield 3; // 暂停,返回 3
console.log("结束");
}
const iterator = generator();
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 }
还可以在next方法中传递参数通过yield接收
function* generator() {
console.log("开始");
let x = yield "请输入数据";
console.log("x:", x);
let y = yield "请再输入";
console.log("y:", y);
}
const iterator = generator();
console.log(iterator.next()); // 输出 "开始" -> { value: "请输入数据", done: false }
console.log(iterator.next(100)); // 输出 "x: 100" -> { value: "请再输入", done: false }
console.log(iterator.next(200)); // 输出 "y: 200" -> { value: undefined, done: true }
yield会暂停生成器的执行直至遇到下一个next()调用。其可暂停、依次处理数据的特点适用于处理大数据、流式数据例如大文件读取、数据库大表读取、视频流读取等场景。