JavaScript中能否读取generator生成器实例的当前返回值?
问题答案
原生JavaScript的生成器(Generator)实例没有提供内置的API可以直接读取上次yield返回的当前值,你示例中用到的.current属性不属于ECMAScript标准定义的内容。
关于设计层面的原因,你的猜测是对的,确实有内存占用的考量:
- 生成器的核心设计目标是实现惰性迭代,适配无限序列、超大集合这类场景,如果默认要求生成器保存最近一次返回值,对于不需要用到历史返回值的场景会产生不必要的内存开销,尤其是当
yield返回的是体积很大的对象、二进制数据时,额外的引用会导致垃圾回收无法及时释放这些资源。 - 另外生成器本质是可暂停执行的状态机,标准层面只定义了它的执行状态、
next/return/throw等控制方法,没有强制要求保存返回值,也是为了尽可能提升灵活性:不同场景对历史返回值的需求差异极大,有的仅需要上一个值,有的需要保留多段历史,这类需求交给开发者根据业务场景自行实现更合理,不会限制生成器的适用范围。
如果要实现你想要的直接读取当前值的能力,除了你给出的同时返回前后值的方案,也可以通过封装给生成器扩展自定义的current属性:
function createRotator(items) { const gen = (function* () { while (true) { for (const item of items) yield item; } })(); // 扩展current属性存储最近一次返回值 gen.current = void 0; // 重写next方法自动更新current const rawNext = gen.next; gen.next = function (...args) { const result = rawNext.apply(this, args); if (!result.done) gen.current = result.value; return result; }; return gen; } // 使用方式 const classRotator = createRotator(['button-green', 'button-yellow', 'button-red']); document.getElementById('my-button').addEventListener('click', e => { // 先移除旧类 e.currentTarget.classList.remove(classRotator.current); // 拿到新类 const newClass = classRotator.next().value; e.currentTarget.classList.add(newClass); });
内容的提问来源于stack exchange,提问作者Robo Robok
相关产品推荐
相关产品推荐

