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

Posted

技术标签:

【中文标题】为啥 Javascript 生成器既是迭代器又是可迭代对象?【英文标题】:Why are Javascript generators both iterators and iterables?为什么 Javascript 生成器既是迭代器又是可迭代对象? 【发布时间】:2018-08-16 16:21:38 【问题描述】:

为什么生成器既是可迭代的又是迭代器的有用/必要?

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

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

$ 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

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

【问题讨论】:

因为您可以在任何可以使用可迭代对象的上下文中使用生成器...!? OK - 那么翻转是问“如果它是一个可迭代的,为什么它也必须是一个迭代器?”集合是可迭代的,而不是迭代器,所以我只是在问为什么生成器需要两者兼而有之? 因为一个迭代器具体只能迭代一次,这是一个关键的区别。 【参考方案1】:

因为它允许解释器机器在需要时无条件地请求一个“新”迭代器,而不必担心迭代器是否已经是一个迭代器。编写代码来实现for/of 循环非常容易,该循环在设置过程中接收到的所有内容上无条件调用.iterator,而不是让每次迭代的启动都执行类型检查以查看它收到的内容是否已经是迭代器与否,只能有条件地调用.iterator

Python 使用相同的迭代器协议;所有迭代器都是可迭代的,它们的等效“getiterator”方法被定义为标识函数。

这在逻辑上也很有意义。 “Iterable”的意思是“能够被迭代”(包括迭代器和可以创建迭代器的东西)。迭代器的概念是可迭代事物概念的超集,因此它们需要提供可迭代接口。

【讨论】:

好的 - 看起来我对教程“生成器对象同时符合可迭代协议和迭代器协议”中的以下评论感到困惑。这让我认为这一定是一些不寻常且值得指出的事情,而说“生成器对象是迭代器”就足够了(这自动暗示它们也是可迭代的,这对所有迭代器都是如此,而不是发电机)。我来自Java,其中Iterable 接口没有扩展Iterator 接口,两者是不同的。 好的——经过更多的实验之后,似乎 javascript 集合的迭代器也是可迭代的,但这只是为了方便起见,并非所有迭代器都必须是可迭代的。 IE。除了next()之外,并非所有迭代器都实现[Symbol.iterator]()

以上是关于为啥 Javascript 生成器既是迭代器又是可迭代对象?的主要内容,如果未能解决你的问题,请参考以下文章

生成器(Generator)

Python 迭代器&生成器

行为型模式之迭代器模式

18设计模式-行为型模式-迭代器模式

python迭代器和生成器

Python小知识:迭代器 vs 可迭代对象 vs 生成器