为什么 Javascript 生成器既是迭代器又是可迭代对象?

Why are Javascript generators both iterators and iterables?

为什么 useful/necessary 生成器既是可迭代对象又是迭代器?

我认为 iterable 和 iterator 是截然不同的,例如一个集合是一个可迭代的,这意味着我可以在它上面请求一个迭代器,每次我这样做我都会得到一个新的迭代器,它允许我单步执行 complete 集合 一次.

生成器看起来最像一个迭代器,即一旦你单步执行它的元素,一旦你不能用它做更多的事情,但除了实现 next() 它还实现了 get-iterator 逻辑可迭代的,但只有这样的逻辑 returns 生成器本身:

$ node
> const genFn = function* () { yield *[1, 2, 3]; }
> const gen = genFn();
> gen.next();
{ value: 1, done: false }
> gen == gen[Symbol.iterator]();
true
> for (const val of gen) console.log(val);
2
3

为什么生成器除了是迭代器之外还必须是可迭代的?

因为它允许解释器机器在需要时无条件地请求一个 "new" 迭代器,而不用担心可迭代对象是否 已经是 一个迭代器。编写用于实现 for/of 循环的代码非常容易,该循环无条件地调用 .iterator 作为设置过程的一部分接收到的所有内容,而不是让每次迭代启动都执行类型检查以查看它是否收到了什么是否已经是迭代器,并且仅有条件地调用 .iterator.

Python 使用相同的迭代器协议;所有迭代器都是可迭代的,其中等效的 "getiterator" 方法被定义为恒等函数。

逻辑上也是有道理的。 "Iterable" 表示 "able to be iterated" (涵盖迭代器和可以创建迭代器的事物)。迭代器的概念是可迭代事物概念的超集,所以他们需要提供可迭代的接口。