首页 > 解决方案 > 同步生成器的每个 `yield` 是否不可避免地分配一个新的 `{value, done}` 对象?

问题描述

MDN 说:

yield 关键字导致对生成器的 next() 方法的调用返回具有两个属性的 IteratorResult 对象: value 和 done。value 属性是对 yield 表达式求值的结果,done 为 false,表示生成器函数还没有完全完成。

我在 Chrome 91.0.4472.77 中进行了测试,每次它似乎都是一个新对象。如果处理是细粒度的(大量迭代,每次计算量低),这似乎非常浪费。为避免不可预测的吞吐量和 GC 卡顿,这是不可取的。

为了避免这种情况,我可以定义一个迭代器函数,在其中我可以控制(确保){value, done}对象的重用,方法是每个都next()导致属性值被修改到位,即。{value, done}新对象没有内存分配。

我是否遗漏了什么,或者生成器是否具有这种固有的垃圾产生性质?{value, done}如果我所做的只是const {value, done} = generatorObject.next();ie ,哪些浏览器足够聪明,不会分配新对象。我不可能掌握这个对象,即。引擎没有理由分配一个新对象?

标签: javascriptiteratorgeneratoryieldgarbage

解决方案


ECMAScript 规范要求生成器为每个 yield 分配一个新对象,因此所有兼容的 JS 引擎都必须这样做。

如果 JS 引擎能够证明程序的可观察行为不会因为这种优化而改变,例如当只在const {value, done} = generatorObject.next()语句中使用生成器时,JS 引擎理论上可以重用生成器的结果对象。但是,我不知道有任何引擎(至少是流行的网络浏览器中使用的引擎)可以做到这一点。由于 JavaScript 的动态特性,这样的优化在 JavaScript 中是一个非常困难的问题。


推荐阅读