如何在生成器函数及其迭代器中获取可迭代对象?
Generator迭代器与可迭代对象的困惑:如何获取生成器的可迭代对象?
我在深入探究GeneratorFunction与Generators的底层实现,想要给IteratorResult及其value添加实用属性,但卡在了核心问题上:如何获取生成器函数提供的实际可迭代对象,而非迭代器?
已做的尝试与观察
1. 生成器函数的this指向特性
测试发现,生成器函数执行时,无论首次调用还是调用next()后继续执行,this值始终为全局对象:
function* range(start = 0, end = Infinity, step = 1) { console.debug("awon", this); for(let i = start; Math.sign(step)*(end - i) > 0; i += step) { console.debug("tawoo", this); i = (yield i)||i; // 可通过next(arg)实现回退或跳过的灵活技巧 console.debug("esree", this); } }
2. 获取Generator原型用于扩展
通过以下方式获取Generator原型,目的是为其扩展map、reduce、filter等实用方法:
const Generator_prototype = Object.getPrototypeOf(range.prototype);
3. 尝试拦截迭代器创建
我替换了[Symbol.iterator]方法,试图拦截迭代器对象的创建并关联到可迭代对象:
const originalIterate = Generator_prototype[Symbol.iterator]; function iterate() { console.log("iter", this); const iterator = originalIterate.apply(this); iterator.parent = this; return iterator; } Generator_prototype[Symbol.iterator] = iterate;
4. 修改next()返回的迭代结果
同时重写了next()方法,尝试对返回的IterationResult做自定义处理:
const originalNext = Generator_prototype.next; function next(...args) { console.log("next", this); let value = originalNext.apply(this, args); if(this.decorate) value = this.decorate(value); return this.current = value; } Generator_prototype.next = next;
执行结果与核心困惑
执行[...range(1,3)]后得到输出:
iter range {<suspended>} next range {<suspended>, parent: range} next range {<suspended>, parent: range, current: {…}} next range {<suspended>, parent: range, current: {…}} > (2) [1, 2]
我发现始终只能拿到迭代器,无法获取预期的可迭代对象。更困惑的是,调用[Symbol.iterator]时,this指向的就是该方法要返回的迭代器本身:
iterator = range(1,3)[Symbol.iterator]() iterator.parent == iterator // > true
替换@@iterator方法后,调用时this已是迭代器,完全不符合预期。到底该如何获取生成器对应的可迭代对象而非迭代器?
内容的提问来源于stack exchange,提问作者Gunther Schadow
相关产品推荐
相关产品推荐

