可迭代Getter语法探讨:能否声明类生成器函数的Getter?
能不能让Getter表现得像生成器函数?
好问题!咱们来聊聊这个——目前JavaScript/TypeScript并没有原生支持“生成器Getter”的语法,但可以通过一些写法实现类似的效果,先拆解你尝试的几种情况:
你的尝试分析
Test1:生成器方法,不是Getter
这种写法是合法的,但它本质是类的生成器方法,调用时需要执行foo.Test1()才能得到迭代器,而不是直接通过Getter访问foo.Test1,不符合你想要的Getter使用方式。class Foo { * Test1(): IterableIterator<string> { // 可以运行,但这不是Getter... yield "Hello!"; } } // 使用:需要调用方法 for (const str of new Foo().Test1()) { console.log(str); }Test2 & Test3:语法错误
不管是* get Test2还是get * Test3,都是不符合JS/TS语法规范的写法。语言本身不支持将Getter与生成器语法直接组合,所以引擎会直接抛出语法错误。Test4:可行但不够简洁的方案
这种写法是有效的——Getter内部返回一个立即执行的生成器函数,这样访问foo.Test4时就能直接得到迭代器,完全符合Getter的使用方式。唯一的缺点是写法稍微啰嗦了点。class Foo { get Test4(): IterableIterator<string> { // 可以运行,但语法不够简洁... return function* (): IterableIterator<string> { yield "Hello!"; }(); } } // 使用:直接访问Getter for (const str of new Foo().Test4) { console.log(str); // 输出 Hello! }
优化后的简洁写法
可以把内部的生成器函数简化一下,去掉冗余的类型标注(TS能自动推断迭代器类型),让代码更清爽:
class Foo { get Test(): IterableIterator<string> { // 简化后的IIFE生成器写法 return (function* () { yield "Hello!"; yield "TypeScript!"; })(); } }
注意事项
- 每次访问这个Getter,都会生成一个新的迭代器实例,所以每次遍历都会从头开始,这在大多数场景下是符合预期的。
- 如果需要复用同一个迭代器,可以把生成器实例存在类的私有属性里,Getter返回它,但要注意迭代器耗尽后就无法再次遍历的问题。
内容的提问来源于stack exchange,提问作者Matěj Pokorný
相关产品推荐
相关产品推荐

