生成器是否同时返回迭代器和可迭代对象?

3

从我之前提出的这个问题中,我了解到for...of期望一个可迭代对象,也就是说,该对象(或其原型链中的一个对象)必须具有带有@@iterator键的属性,该属性可以通过常量Symbol.iterator获得。

因此,可迭代对象看起来应该像这样:

实现@@iterable方法的对象。

所以,一个可迭代对象应该长这样:

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]方法的权限?

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

1个回答

3
简而言之,生成器既是可迭代对象又是迭代器。
来自MDN的链接
生成器对象由生成器函数返回,并符合可迭代协议和迭代器协议。
通过调用返回的生成器对象的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);
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接