JavaScript中的迭代器

86 阅读2分钟

JS中,迭代器 是一个对象,它定义了一个 next() 方法,每次调用 next() 都会返回一个对象 { value, done }for...of、展开运算符 ...Array.from() 等都依赖于迭代器,ArraySetMapString等数据结构都支持相同方式遍历,迭代器遍历时不会一次性加载所有数据,而是在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()调用。其可暂停、依次处理数据的特点适用于处理大数据、流式数据例如大文件读取、数据库大表读取、视频流读取等场景。