如何以官方方式为JavaScript的Generator.prototype添加方法?
给所有JavaScript生成器添加map方法的官方可行方式
首先明确:JavaScript没有全局暴露的Generator构造函数,所以没办法像给Array.prototype补全方法那样,直接通过xxx.Generator.prototype这种写法来给所有生成器添加方法。目前最规范的实现方式,就是通过获取生成器的内部原型来扩展。
具体实现步骤
- 获取生成器的通用原型
我们可以通过一个空的生成器函数,用Object.getPrototypeOf拿到所有生成器对象共享的原型(规范里叫%GeneratorPrototype%):
// 获取生成器的通用原型 const GeneratorPrototype = Object.getPrototypeOf(function* () {});
- 给原型添加map方法
和补全Array的map方法逻辑一致,先判断方法是否存在,再添加:
if (!GeneratorPrototype.map) { GeneratorPrototype.map = function* (fn) { for (const item of this) { yield fn(item); } }; }
验证效果
用你写的range生成器测试链式调用:
function* range(start = 0, end = Infinity, step = 1) { for(let i = start; Math.sign(step)*(end - i) > 0; i += step) yield i; } // 链式调用map [...range(8,0,-1).map(x => 2**x).map(x => x-1)] // 输出:[255, 127, 63, 31, 15, 7, 3, 1]
为什么这是最规范的方式?
__proto__是早期浏览器的非标准属性,虽然现在多数环境支持,但规范中更推荐使用Object.getPrototypeOf来获取对象原型,避免依赖非标准特性。- 每个生成器函数的
prototype,其原型链顶端都是%GeneratorPrototype%,所以修改这个原型后,所有生成器对象(包括你自己写的生成器、map返回的生成器)都会继承到map方法,自然支持链式调用,不需要单独给map的原型再添加方法。
关于你提到的wu.js
wu.js这类库通常是通过包装生成器对象来实现链式操作,本质是创建新的迭代器包装器,而非直接修改原型。如果你想要直接给原生生成器扩展方法,上面的原型修改方式就是最直接且符合规范的做法,不存在更"官方"的直接写法——因为JS本身没把Generator构造函数暴露到全局。
内容的提问来源于stack exchange,提问作者Gunther Schadow
相关产品推荐
相关产品推荐

