【问题标题】:Do Generators return both an iterator and an iterable?生成器是否同时返回迭代器和可迭代对象?
【发布时间】:2018-06-21 17:28:27
【问题描述】:

this question I asked before 我了解到for...of 需要一个可迭代对象,即

实现@@iterable 方法的对象,这意味着该对象(或其原型链上的对象之一)必须具有带有@@iterator 键的属性,该键可通过常量Symbol.iterator 获得

所以,一个可迭代对象看起来像这样:

const iterableObject: {
  [Symbol.iterator]: function someIteratorFunction() {
    //...
  }
}

另一方面,我们有生成器,如下所示:

function* generatorFoo(){
  yield 1;
  yield 2;
  yield 3;
  yield 4;
}

并且可以在for...of 结构中使用,如下所示:

for(const item of generatorFoo())
  console.log(item);

因此,调用generatorFoo() 返回一个可迭代对象,因为for...of 处理它没有问题。我也可以调用generatorFoo()[Symbol.iterator]() 并接收一个迭代器来确认这一点。

但是,调用 generatorFoo 也会返回一个迭代器,因为我可以调用 generatorFoo() 我得到一个对象,该对象使用方法 next 来获取迭代器的下一个值,如下所示:

const iteratorFromGen = generatorFoo();
iteratorFromGen.next().value; //1
iteratorFromGen.next().value; //2
iteratorFromGen.next().value; //3
iteratorFromGen.next().value; //4

这是否意味着调用生成器函数会返回一个可以访问next 方法 [Symbol.iterator] 方法的对象?

当调用生成器函数时,我们是否得到一个既是迭代器又是可迭代对象的对象?这是如何实现的?

【问题讨论】:

    标签: javascript iterator iterable


    【解决方案1】:

    简而言之,是的,生成器既是可迭代的又是迭代器。

    From MDN:

    Generator 对象由生成器函数返回,它 符合可迭代协议和迭代器协议。

    调用返回的生成器对象的Symbol.iterator方法返回的迭代器与生成器对象本身相同。例如:

    function* gen() {
      let i = 0;
      while (i < 10) yield i++;
    }
    
    const iterableIterator = gen();
    console.log(iterableIterator === iterableIterator[Symbol.iterator]()); // true

    您甚至可以通过遵循迭代器协议并使用返回thisSymbol.iterator 方法来轻松复制该模式。比如:

    class MyIterableIterator {
      
      constructor(arr) {
        this.arr = arr;
        this.i = 0;
      }
    
      [Symbol.iterator]() {
        return this;
      }
      
      next() {
        if (this.i === this.arr.length) return {done: true}
        return {value: this.arr[this.i++], done: false}
      }
    }
    
    const iterableIterator = new MyIterableIterator([1, 2, 3, 4, 5]);
    console.log(iterableIterator === iterableIterator[Symbol.iterator]()); // true
    
    // Works fine if you call next manually, or using a for-of loop.
    console.log(iterableIterator.next())
    for (let item of iterableIterator) {
      console.log(item);
    }

    【讨论】:

      猜你喜欢
      • 2017-12-18
      • 2018-08-16
      • 1970-01-01
      • 1970-01-01
      • 2020-06-29
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      • 2023-03-20
      相关资源
      最近更新 更多