代码之家  ›  专栏  ›  技术社区  ›  Sammy I.

我能用一个简单的函数做一个迭代器吗?(没有生成器或符号.迭代器)

  •  1
  • Sammy I.  · 技术社区  · 6 年前

    我一直在尝试使用一个普通函数,不使用生成器或 Symbol.iterator 学术协议。为此,我创建了一个函数,它返回一个带有 next 参数,但尝试将其作为 iterable 论证 for...of 循环产生不需要的结果。

    这是我的代码,我从 Iterators and Generators page on MDN :

    function iterateThis(arr){
        let i = 0;
        return {
            next: function() {
                return i < arr.length ?
                    {value: arr[i++], done: false} :
                    {done: true};
            }
         };
    }
    

    如果我试着像这样运行它:

    const iterable = iterateThis([1,2,3,4,5]);
    for(item in iterable){
        console.log(item);
    }
    

    在控制台上,我只得到一个结果: 下一个 .

    在函数的创建过程中我是否做错了什么? iterateThis ?或者是 为了…… 仅设计用于与发电机和 symbol.迭代器 财产?

    在节点V8.11.1上执行

    1 回复  |  直到 6 年前
        1
  •  4
  •   CRice    6 年前

    问题是你的 iterateThis 函数返回 迭代器 但是 for/of 构造需要 可迭代的 .

    好吧,等等,有什么区别?

    MDN's page on iteration protocols :

    为了 可迭代的 ,对象必须实现 @@iterator 方法,意味着对象(或其上的一个对象 原型链)必须具有 @ @迭代器 钥匙是什么 通过常量可用 Symbol.iterator :

    另一方面:

    对象是 迭代器 当它实现 next() 方法与 以下语义: ommited由于长度,tl;dr:下一个方法 返回窗体的对象: {value: T, done: boolean}

    他们有联系,打电话给 @ @迭代器 AN方法 可迭代的 返回一个 迭代器 .

    这个 为/ 循环总是需要iterable,因此如果您想使用 为/ ,你必须使用 @ @迭代器 / symbol.迭代器 . 据我所知,这是不可能的。但是,您的代码片段可以很容易地修改为使用它,只需创建一个对象,当 symbol.迭代器 方法被调用:

    function iterateThis(arr){
        let i = 0;
        return {
            next: function() {
                return i < arr.length ?
                    {value: arr[i++], done: false} :
                    {done: true};
            }
         };
    }
    
    function makeIterableFromIterator(iterator) {
      return {
        [Symbol.iterator]: function() {
          return iterator;
        }
      }
    }
    
    const iterator = iterateThis([1, 2, 3, 4, 5]);
    const iterable = makeIterableFromIterator(iterator);
    
    for (item of iterable) {
      console.log(item);
    }