【问题标题】:Are there use cases where you would manually implement an iterator yourself?是否存在您自己手动实现迭代器的用例?
【发布时间】:2020-08-10 07:48:29
【问题描述】:

iterator 经常使用,例如在spread 运算符、for/of-loop、解构等中。但它们是隐藏的。我想知道是否存在您会积极使用如何实现迭代器的知识的用例?

例如,使用迭代器对数组进行迭代过于复杂,如下所示,我不知道为什么有人会自己实现迭代器:

function arrayIterable(arr = []) {
    let index = 0;
    const len = arr.length;

    const arrayIterator = {
       next: () => {
           let result;
           if (index === len) {
             return { value: arr[index], done: true };            
           }
           result = { value: arr[index], done: false }
           index++;
           return result;           
       }
    };
    return arrayIterator;
}
const myArr = ['a','b','c','d'];
let iter = arrayIterator(myArr);
let result = iter.next();
while (!result.done) {
  console.log(result.value);
  result = iter.next();
}

【问题讨论】:

  • 您是否在询问手动实现迭代器(而不是使用生成器函数),询问手动调用迭代器(而不是使用@ 987654325@/yield*),还是两者兼有?
  • "例如,迭代数组" - 嗯,这是一个非常糟糕的例子,因为迭代数组是一个已解决的问题,并且不需要迭代器。
  • @Bergi 手动实现迭代器。背景:我正在阅读有关迭代器的内容,并在思考如何在日常工作中使用这些知识。除了知道它是如何在幕后工作的之外,我还在寻找我会真正积极使用它的用例。
  • 您已得到答案,欢迎评论。
  • 在这种情况下,在 99% 的情况下,使用生成器函数可以更轻松地完成任务。如果您想添加不属于迭代协议的额外功能,您只需要自己实现迭代器对象,例如前瞻、访问当前值、缓存内容、制作没有隐式排队的异步迭代器,或者实际上只是任何功能需要直接访问正在运行的迭代器的状态。

标签: javascript loops iterator


【解决方案1】:

如果您想懒惰地操作数据集,这很方便。一个流、一个文件、一个数据库,你从一个行/记录移动到另一个并推进迭代器。无需将历史记录保存在内存中。

由于您不必在内存中维护整个源,您还可以处理无限数据源的情况。

迭代器的最大优势在于客户端。在 pre-iterator 时代的代码中,您通常会得到一个类似数组的对象来公开索引。但是,在现代代码中,您可以得到一个迭代器,这意味着客户端使用相同的代码处理更一般的结果。示例案例参考this question下的讨论。

【讨论】:

    【解决方案2】:

    我不认为它是如何实现的知识会被用来实际迭代这个东西。这与使用 for of 循环相比没有任何优势。

    但假设您正在构建一个 JavaScript 库,例如用于 MongoDB 数据库的 Node.js 驱动程序。你想让查询数据库和循环结果变得容易。你实现iterable protocol,然后人们可以这样做:

    const cursor = queryDatabase(<some query>)
    for (let doc of cursor) {
    // do something with doc
    }
    

    事实上,the MongoDB Driver really does do this(除了他们实现了一个异步迭代器)。

    编辑:请注意使用迭代器协议比从queryDatabase() 返回类似数组的对象的好处。特别是在 MongoDB 中,cursor 并不包含所有结果。是句柄,可以调用cursor.next()获取查询结果

    正如您在问题中指出的那样,必须致电 cursor.next() 的问题在于它非常笨拙。然而这很好,因为不需要从数据库中获取所有结果,其中可能有数千个。因此,迭代器协议是一种保持cursor.next() 优点的方法,而无需处理丑陋的语法。

    【讨论】:

    • 是的,我也是这么想的。如果您想自己实现库或框架,则只需要这些知识。除了知道如何实现迭代器之外没有任何实用价值。
    • 这只是部分回答了这个问题。如果将结果作为类似数组的对象给出,那么数据库查询将同样易于使用。
    • @WiktorZychla 我同意。应该注意的是,在这个 Node 驱动程序的特定示例中,使用迭代器而不是 array-ilke 对象是有好处的。类数组对象的缺点是它必须保存所有结果,但cursor 通过调用cursor.next() 从数据库中获取结果,因此迭代器协议是笨重的一个很好的替代方案cursor.next 语法,没有类数组对象的缺点,必须获取所有结果。
    【解决方案3】:

    您可以在 MDN 上找到 JavaScript 中迭代器技术的全面介绍:

    MDN: Iteration protocols

    它还包含应用领域、用途和示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-11
      • 2011-11-10
      • 1970-01-01
      • 2023-01-28
      • 2021-11-30
      • 2015-09-12
      • 1970-01-01
      • 2011-02-09
      相关资源
      最近更新 更多