MST

星途 面试题库

面试题:JavaScript 生成器与迭代器协议的深度理解

深入阐述 JavaScript 生成器如何与迭代器协议紧密结合。描述生成器对象自身如何满足迭代器协议,以及如何通过自定义迭代器使一个对象能够被生成器函数消费。请实现一个自定义的可迭代对象,并编写一个生成器函数来处理这个对象,展示两者之间的交互机制,同时分析这种机制在复杂数据处理场景中的应用和优化策略。
27.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

JavaScript 生成器与迭代器协议的紧密结合

  1. 生成器对象满足迭代器协议
    • 迭代器协议规定,一个迭代器对象必须有一个 next() 方法。当调用 next() 方法时,它返回一个包含 valuedone 属性的对象。
    • 生成器函数通过 yield 关键字暂停和恢复执行,生成器对象(由生成器函数调用返回)自然地满足迭代器协议。每次调用生成器对象的 next() 方法,生成器函数执行到下一个 yield 语句,yield 后面的值作为 next() 方法返回对象的 value,当生成器函数执行完毕,donetrue
    • 例如:
function* myGenerator() {
    yield 1;
    yield 2;
    return 3;
}
const gen = myGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: true }
  1. 自定义迭代器使对象能被生成器函数消费
    • 要使一个对象可迭代,需要为其定义一个 Symbol.iterator 方法,该方法返回一个迭代器对象(满足迭代器协议)。
    • 生成器函数可以消费这样的可迭代对象,通过 for...of 循环等方式。for...of 循环会自动调用可迭代对象的 Symbol.iterator 方法获取迭代器,然后不断调用迭代器的 next() 方法。
    • 例如,实现一个自定义的可迭代对象 MyIterable
const MyIterable = {
    data: [1, 2, 3],
    [Symbol.iterator]: function() {
        let index = 0;
        return {
            next: () => {
                if (index < this.data.length) {
                    return { value: this.data[index++], done: false };
                } else {
                    return { value: undefined, done: true };
                }
            }
        };
    }
};
function* consumeIterable() {
    for (let value of MyIterable) {
        yield value * 2;
    }
}
const consumer = consumeIterable();
console.log(consumer.next()); // { value: 2, done: false }
console.log(consumer.next()); // { value: 4, done: false }
console.log(consumer.next()); // { value: 6, done: false }
console.log(consumer.next()); // { value: undefined, done: true }

交互机制在复杂数据处理场景中的应用和优化策略

  1. 应用
    • 惰性求值:生成器和迭代器结合实现惰性求值,在处理大数据集时,不会一次性加载所有数据到内存,而是按需生成和处理数据。例如,处理一个非常大的文件,逐行读取并处理,而不是将整个文件读入内存。
    • 异步操作控制:在异步场景中,可以利用生成器和迭代器实现异步操作的顺序控制。通过 yield 暂停生成器,等待异步操作完成后再恢复执行。比如,使用 yield 暂停等待 Promise 解决,从而实现顺序执行多个异步任务。
  2. 优化策略
    • 减少中间数据存储:在生成器处理数据过程中,尽量避免创建大量中间数据结构。例如,在对数据进行多步转换时,可以通过链式调用生成器,直接从一个生成器输出流入下一个生成器输入,减少中间数组等数据结构的创建。
    • 缓存中间结果:对于一些重复计算的部分,可以缓存中间结果。如果生成器在不同阶段会多次使用某个计算结果,可以在第一次计算后将其缓存起来,后续直接使用缓存值,提高效率。