繁体   English   中英

如何扩展Generator类?

[英]How to extend the Generator class?

我试图过滤一个生成器,并期望必须在JavaScript中的任何地方定义这种通用功能,因为它是为数组定义的,但我找不到它。 所以我试着定义它。 但我不能扩展内置的发电机。

我有一个示例生成器

function make_nums ()
{
  let nums = {};
  nums[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
  };
  return nums;
}

产生一些数字。

[...make_nums()] // => Array [ 1, 2, 3 ]

如果我构建一个数组,我可以通过使用数组的filter函数来filter数组。

[...make_nums()].filter(n => n > 1) // => Array [ 2, 3 ]

但我不想建立一个数组。 相反,我想采用旧的生成器并构建一个新的过滤生成器。 为此我写了以下函数。

function filtered (generator, filter)
{
  let g = {};
  g[Symbol.iterator] = function* () {
    for (let value of generator)
      if (filter(value))
        yield value;
  };
  return g;
}

这可以用来做我想要的。

[...filtered (make_nums(), n => n > 1)] // => Array [ 2, 3 ]

但这是一个非常通用的函数,它可以应用于每个生成器,就像filter函数可以应用于每个Array 所以我试图扩展生成器一般,但我不明白如何。

生成器的MDN文档以某种方式表明Generator.prototype可能存在,但它似乎不存在。 当我尝试在Generator.prototype定义一些东西时,我得到了错误

ReferenceError:未定义Generator

如何扩展内置的Generator类?

传统的警告说,扩展内置原型不一定是最好的想法,并且要谨慎做到这一点,你可以获得生成器函数原型

const genproto = Object.getPrototypeOf(function*(){});

有了它,你可以添加filter()功能:

Object.defineProperty(genproto, "filter", {
  value: function*(predicate) {
    for (let value of this())
      if (predicate(value)) yield value;
  }
});

因此:

console.log([... function*() {
    for (let i = 0; i < 10; i++) yield i;
  }.filter(value => value % 2 === 0)
]);

将打印[0, 2, 4, 6, 8]

要明确:这个答案是关于扩展生成器函数的原型,而不是生成器对象本身。 因此,这将确保程序中的每个生成器函数都可以使用.filter()方法和任何其他类似的扩展。

事实证明,我对GeneratorIterable感到困惑。 我以为我必须扩展Generator ,但实际上扩展Iterable就足够了。 事实上, Iterable似乎也没有被JavaScript定义,因此很容易定义它,以避免修改内置原型的问题。

这实际上做了我试图实现的目标。

class Iterable {
  constructor (generator) {
    this[Symbol.iterator] = generator;
  }
}

Iterable.prototype.filter = function (predicate) {
  let iterable = this;
  return new Iterable (function* () {
    for (let value of iterable)
      if (predicate (value))
        yield value;
  });
};

我可以创建Iterables

make_nums = new Iterable(function* () { yield 1; yield 2; yield 3; });

可以使用它们

[...make_nums] // => Array [ 1, 2, 3 ]

并可以过滤它们

[...make_nums.filter(n => n > 1)] // => Array [ 2, 3 ]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM