如何在for..of循环向迭代器传自定义值?生成器方案是否最优?
JS可迭代对象迭代传参相关问题
首先看原始的自定义可迭代对象实现:
class MyIterable { val = 1; [Symbol.iterator]() { return { next: () => { return { done: this.val > 3, value: this.val++ } } } } } for(const v of new MyIterable()){ console.log(v); }
问题1:能否在每次迭代时向next()方法传递新值?
for..of循环本身不支持直接向每次迭代的next()传递参数,你给出的伪代码语法是无效的——for..of的底层逻辑是自动调用迭代器的next()方法,且不会传入任何自定义参数。
如果要实现向next()传参的需求,你需要手动调用迭代器的next()方法,而不是依赖for..of的自动迭代。示例如下:
class MyIterable { val = 1; [Symbol.iterator]() { return { next: (a,b,c) => { return { done: this.val > a, value: this.val + b + c } } } } } // 手动迭代并传递参数 const iter = new MyIterable()[Symbol.iterator](); let a = 3, b = 4, c = 5; let res = iter.next(a, b, c); while (!res.done) { console.log(res.value); // 可动态修改参数 a = 5; res = iter.next(a, b, c); }
你提到的提前终止、过滤结果这类场景,除了通过向next()传参实现,也可以通过在迭代器内部维护状态、或者用生成器封装过滤逻辑来完成,但如果确实需要动态传递参数给每次next()调用,手动迭代是最直接的方式。
问题2:给定的generate生成器函数是否是迭代时传递自定义值的最优实现?
这个生成器的思路可行,但算不上“最优”,可以从写法和灵活性上优化:
原始实现的问题:
- 无需使用
iterator.next.apply(iterator,[a,b,c]),直接调用iterator.next(a,b,c)即可,next方法本身支持接收参数。 while(1)的死循环写法不够直观,换成条件循环更易读。- 当前写法无法支持动态修改参数——生成器初始化时仅接收一次参数,外部后续修改参数值不会同步到生成器内部(参数按值传递)。
优化后的生成器实现:
// 支持任意数量参数的版本 const generate = function*(iterator, ...args) { let { done, value } = iterator.next(...args); while (!done) { yield value; ({ done, value } = iterator.next(...args)); } };
使用场景说明:
- 如果参数固定不变,这个生成器是简洁的封装,能让你继续使用for..of循环语法。
- 如果需要动态修改每次迭代的参数,当前写法不适用,此时手动调用next()更灵活;或者可以把参数放在引用类型(如对象)中,让生成器内部引用对象属性,外部修改属性时生成器能拿到最新值:
const generate = function*(iterator, params) { let { done, value } = iterator.next(params.a, params.b, params.c); while (!done) { yield value; ({ done, value } = iterator.next(params.a, params.b, params.c)); } }; // 使用方式 const params = {a:3, b:4, c:5}; for(const v of generate(new MyIterable()[Symbol.iterator](), params)){ console.log(v); // 动态修改参数 params.a = 5; }
内容的提问来源于stack exchange,提问作者Alexander Mills
相关产品推荐
相关产品推荐

