为什么Javascript`theerator.next()`返回一个对象?

Chr*_*ing 6 javascript performance memory-management iterable ecmascript-6

救命!我在C#编程很长一段时间后学会喜欢Javascript,但我学会爱上可迭代协议!

为什么Javascript采用需要为每次迭代创建新对象的协议?为什么要next()返回一个新的对象具有属性donevalue代替采用类似C#这样的协议IEnumerable以及IEnumerator其在需要两个电话的费用不分配对象(一到moveNext,看看是否迭代完成,第二,以current获取价值)?

是否存在漏洞优化,跳过对象返回的分配next()?很难想象,假设迭代不知道一旦返回就可以使用该对象......

生成器似乎没有重用下一个对象,如下所示:

function* generator() {
  yield 0;
  yield 1;
}

var iterator = generator();
var result0 = iterator.next();
var result1 = iterator.next();

console.log(result0.value) // 0
console.log(result1.value) // 1
Run Code Online (Sandbox Code Playgroud)

嗯,这是一个线索(感谢Bergi!):

我们稍后将回答一个重要问题(在第3.2节中):为什么迭代器(可选)在最后一个元素之后返回一个值?这种能力是元素被包裹的原因.否则,迭代器可以简单地在最后一个元素之后返回一个公开定义的sentinel(停止值).

并在Sect.3.2他们讨论使用Using generator作为轻量级线程.似乎说返回一个对象的原因next是,value即使done是,也可以返回true!哇.此外,可以生成return除了值yieldyield*-ing值和一个值,生成由return作为最终valuedonetrue!

所有这些都允许伪线程.而这个功能,伪线程,值得为循环中的每一次分配一个新对象... Javascript.总是如此意外!


虽然,现在我考虑一下,允许yield*"返回"一个值以启用伪线程仍然不能证明返回一个对象是正确的.该IEnumerator协议可以扩展后返回一个对象moveNext()的回报false-只需添加一个属性hasCurrent测试迭代完成后,当true指示current有一个有效的价值?

编译器优化并非易事.这将导致迭代器性能的相当大的变化......这不会导致库实现者出现问题吗?

在友好的SO社区发现的这个主题中提出了所有这些要点.然而,这些论点似乎没有成功.


但是,无论是否返回一个对象,迭代完成后都没有人会检查一个值,对吧?例如,大多数人都会认为以下内容会记录迭代器返回的所有值:

function logIteratorValues(iterator) {
  var next;
  while(next = iterator.next(), !next.done)
    console.log(next.value)
}
Run Code Online (Sandbox Code Playgroud)

只是它不因为即使donefalse迭代器仍然有可能返回另一个值.考虑:

function* generator() {
  yield 0;
  return 1;
}

var iterator = generator();
var result0 = iterator.next();
var result1 = iterator.next();

console.log(`${result0.value}, ${result0.done}`) // 0, false
console.log(`${result1.value}, ${result1.done}`) // 1, true
Run Code Online (Sandbox Code Playgroud)

迭代器是在"完成"真的是迭代器之后返回一个值吗?单手拍手的声音是什么?这看起来很奇怪......


这里是深入职位上的发电机我很喜欢.与迭代集合成员相反,花费大量时间来控制应用程序的流程.


另一个可能的解释是IEnumerable/IEnumerator需要两个接口和三个方法,而JS社区更喜欢单个方法的简单性.这样他们就不必引入符号方法组的概念,即接口......

Ber*_*rgi 8

是否存在漏洞优化,跳过对象返回的分配next()

是.那些迭代器结果对象很小,通常是短暂的.特别是在for … of循环中,编译器可以进行简单的转义分析,以查看对象根本不会面向用户代码(但只有内部循环评估代码).它们可以由垃圾收集器非常有效地处理,甚至可以直接在堆栈上分配.

以下是一些消息来源:

  • @ChristopherKing他们首先选择使迭代协议*简单*,只指定它应该如何工作,并信任引擎实现以进行优化.(规范中的语义越简单,编写的代码就越简单,编译器就越容易优化).请注意,ECMAScript规范根本不讨论分配/解除分配. (2认同)