Generator函数需用bind预绑定构造器才能使内部this始终指向目标对象;箭头函数封装或装饰器bindGen是动态绑定的有效简写方式。

在 Generator 函数中,this 默认不绑定到实例(不像普通方法调用那样自动绑定),直接用 genFn.call(obj) 或 genFn.bind(obj) 无法让内部 yield 表达式或后续 next() 调用持续持有该 this。真正可行的简写方式,是借助 箭头函数封装 + 显式传入上下文,或更推荐的——用 bind 包裹整个 Generator 实例化过程,而非仅绑定构造函数。
用 bind 预绑定 Generator 构造器(最简且可靠)
Generator 函数本身是可执行的,但返回的是迭代器对象;而迭代器的 next() 方法在内部执行时,this 指向的是该迭代器实例(不是原始 Generator 函数的调用者)。因此,关键在于:让 Generator 函数体内的逻辑能访问到目标上下文——最直接的方式是在定义阶段就将 this 注入闭包。
- 不推荐:
genFn.bind(obj)()—— 这只绑定了一次执行,返回的迭代器仍无this绑定能力 - 推荐:
function* myGen() { ... } const boundGen = myGen.bind(obj); const iter = boundGen();—— 此时myGen内部的this在每次iter.next()中都指向obj - 注意:
bind对 Generator 函数有效,它会保留其特殊行为(如支持next、throw),且 V8 等引擎已优化该用法
用箭头函数包裹并显式透传 this(适合动态上下文)
当需要在运行时决定 this,或需复用同一 Generator 逻辑于不同对象时,可把 Generator 当作纯函数,用箭头函数“代理”调用:
- 写法:
const createIter = (ctx) => function* () { yield this.val; }.bind(ctx)(); - 效果:
this在yield和后续next()中始终为ctx - 优势:避免重复
bind声明,适合工厂模式;缺点是每次调用都新建闭包
避免常见误区:不要依赖 call/apply 启动后自动维持 this
很多人误以为 genFn.call(obj).next() 能让后续 next() 也保持 this,但实际:
-
genFn.call(obj)返回的是一个迭代器(IteratorObject),它的next是普通方法,this指向该迭代器自身,与obj无关 - Generator 函数体内的
this只在首次执行(即第一次next())时由call/bind决定,之后恢复为迭代器实例 - 验证方式:
function* g() { console.log(this); yield 1; } g.call({x:1}).next(); // {x:1};再调用 .next() 则 this 变成迭代器对象
进阶简写:封装成可复用的装饰器函数
若项目中高频使用绑定上下文的 Generator,可抽象一层:
const bindGen = (genFn, ctx) => genFn.bind(ctx);
// 使用:const iter = bindGen(function* () { yield this.name; }, user)();- 语义清晰,一行完成绑定 + 实例化
- 比手写
bind更易维护,也方便配合 TypeScript 类型推导 - 不侵入原有 Generator 定义,符合关注点分离

















