为何迭代遍历后Generator(生成器)会变为空且无法复用?
问题原因:生成器是一次性迭代器
你遇到的这个情况完全是生成器的设计特性导致的——生成器对象属于一次性迭代器,一旦你通过for...of、Array.from()或者手动调用next()把它遍历完,它内部的状态指针就会停在末尾,后续再尝试遍历的话,不会再产生任何新元素,只会返回done: true的结果。
看你的代码:第一次调用Array.from(myGenerator)已经把生成器的所有元素都取出来了,此时生成器已经被耗尽;之后调用iterateThroughGenerator的时候,for...of循环其实已经没有元素可以遍历了;最后再调用Array.from(myGenerator)自然会得到长度为0的空数组。
几种解决办法
1. 每次遍历前重新创建生成器实例
生成器函数(比如你的generatorFunc)每次调用都会返回一个全新的生成器对象,只要你的生成器函数不依赖外部可变状态,这种方式最简单直接:
// 第一次遍历:创建新生成器 console.log(Array.from(this.generatorFunc()).length); // 输出N // 第二次遍历:再创建一个新生成器 this.iterateThroughGenerator(this.generatorFunc()); // 第三次遍历:依旧创建新生成器 console.log(Array.from(this.generatorFunc()).length); // 还是输出N
2. 提前缓存生成器的结果为数组
如果生成器的元素数量不大,或者你需要反复使用这些元素,直接把生成器的所有元素转换成数组保存起来——数组是可以被多次遍历的:
// 一次性把生成器的元素转成数组缓存 let generatorItems = Array.from(this.generatorFunc()); console.log(generatorItems.length); // 输出N // 遍历缓存的数组 this.iterateThroughGenerator(generatorItems); // 再次使用数组,长度依旧是N console.log(generatorItems.length); // 输出N // 你的迭代函数不需要修改,因为数组也支持for...of循环 iterateThroughGenerator(generator) { for(let element of generator) { // 原有的逻辑代码 } }
3. 包装成可重复迭代的对象
如果你想保留生成器“按需生成元素”的特性(比如元素数量极大,不想一次性加载到内存),可以把生成器函数包装成一个可重复迭代的对象,每次遍历都会自动创建新的生成器实例:
// 包装类:每次调用迭代器都返回新的生成器 class ReusableGeneratorWrapper { constructor(generatorFunc) { this.generatorFunc = generatorFunc; } // 实现可迭代接口 [Symbol.iterator]() { return this.generatorFunc(); } } // 使用方式 let myReusableGen = new ReusableGeneratorWrapper(() => this.generatorFunc()); console.log(Array.from(myReusableGen).length); // 输出N this.iterateThroughGenerator(myReusableGen); // for...of会自动获取新生成器 console.log(Array.from(myReusableGen).length); // 依旧输出N
内容的提问来源于stack exchange,提问作者TomLisankie
相关产品推荐
相关产品推荐

