向 Generator.prototype 添加方法的官方方法是什么?

问题描述 投票:0回答:1

我对 JavaScript 生成器完全陌生。我对 Java 迭代器有很多实际经验,并且用 Java 迭代器链完成了所有软件工作。但我现在才刚刚发现 JavaScript 中的生成器函数和yield,甚至yield*。我想以某种方式添加地图和归约功能。让我们从地图开始吧。

是的,我看过 wu.js,但对我来说,这看起来太像黑客了。一般来说,不反对重新包装,但我有预感,它可以更直接地完成。

这是我所拥有的,首先是范围生成器函数:

function* range(start = 0, end = Infinity, step = 1) { 
    for(let i = start; Math.sign(step)*(end - i) > 0; i += step)
        yield i;
}

[...range(8,0,-1)] // > [8, 7, 6, 5, 4, 3, 2, 1]

太酷了。现在我该如何添加我的地图功能?我发现了这个:

range.prototype > 发电机 {}

看起来这个 Generator {} 正在邀请我在上面添加一些方法!所以我可以在该范围原型上添加地图:

range.prototype.map = function*(fn) { 
    for(let x of this)
        yield fn(x);
}

[...range(8,0,-1).map(x => 2**x)] // > [256, 128, 64, 32, 16, 8, 4, 2]

哇!但如果我想用一张地图跟随另一张地图,我需要先说这一点:

range.prototype.map.prototype.map = range.prototype.map
[...range(8,0,-1).map(x => 2**x).map(x => x-1)] // > [255, 127, 63, 31, 15, 7, 3, 1]

但我想在所有发电机上粘贴地图。当 IE 恐龙版本 8 上尚不支持数组函数时,我这样做了:

if(!Array.prototype.map)
    Array.prototype.map = function(fn) { 
        var r = []; 
        for(var i = 0; i < this.length; i++) 
            r.push(fn(this[i], i, this);
    }

这让我可以在 IE 恐龙版 8 中工作,就像在任何像样的浏览器中一样。不需要古怪的 Util.arrayMap(...) 函数。所以我现在很想这样做:

if(!Generator.prototype.map)
    Generator.prototype.map = = function*(fn) { 
        for(let x of this)
            yield fn(x);
    }

但是呃哦,Generator 不像 Array 那样是全局定义的名称!所以我偷偷溜进去:

range.prototype.__proto__.map = function*(fn) { 
    for(let x of this) {
      yield fn(x);
    }
}

[...range(8,0,-1).map(x => 2**x).map(x => x-1)] // > [255, 127, 63, 31, 15, 7, 3, 1]

宾果!我做到了。为了避免使用

__proto__
我也可以这样做:

Object.getPrototypeOf(range.prototype).map = ...

达到同样的效果。

但是除了用这个

range.prototype._proto_
技巧从侧门潜入之外,难道没有更正式的方法吗?

通过更正式的方式,我的意思是直接说一些事情,例如

xxx.Generator.prototype.map = ...

其中 xxx 是定义在其中的任何模块或某些此类 Generator 类?

javascript iterator mapreduce generator
1个回答
0
投票

我想以某种方式添加一个映射和一个归约函数。

从 ECMAScript 2025 开始,这些可作为迭代器辅助方法使用,因此您不再需要创建它们。本机函数返回的迭代器对象是继承这些方法的迭代器辅助对象;对于发电机来说也是如此:

// Your generator
function* range(start=0, end=Infinity, step=1) { 
    for (let i = start; Math.sign(step) * (end - i) > 0; i += step)
        yield i;
}

// Your example adapted to make use of iterator helper methods:
const result = range(8, 0, -1)
               .map(x => 2**x)
               .map(x => x-1)
               .toArray();
               
console.log(result); // > [255, 127, 63, 31, 15, 7, 3, 1]

请注意,您可以使用扩展语法来获取数组,但我喜欢链接

toArray()
方法(这也是一个迭代器辅助方法)。在我看来,它只是让它看起来更优雅。

© www.soinside.com 2019 - 2024. All rights reserved.