[英]How to extend the Generator class?
I tried to filter a generator and had the expectation that this kind of general functionality must be defined anywhere in JavaScript, because it is defined for Arrays, but I can not find it. 我试图过滤一个生成器,并期望必须在JavaScript中的任何地方定义这种通用功能,因为它是为数组定义的,但我找不到它。 So I tried to define it.
所以我试着定义它。 But I can not extend the built-in generators.
但我不能扩展内置的发电机。
I have an example generator 我有一个示例生成器
function make_nums ()
{
let nums = {};
nums[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
return nums;
}
generating some numbers. 产生一些数字。
[...make_nums()] // => Array [ 1, 2, 3 ]
If I build an array, I can filter the array by the use of the filter
function for arrays. 如果我构建一个数组,我可以通过使用数组的
filter
函数来filter
数组。
[...make_nums()].filter(n => n > 1) // => Array [ 2, 3 ]
But I do not want to build an array. 但我不想建立一个数组。 Instead I want to take the old generator and build a new filtering generator.
相反,我想采用旧的生成器并构建一个新的过滤生成器。 For this I wrote the following function.
为此我写了以下函数。
function filtered (generator, filter)
{
let g = {};
g[Symbol.iterator] = function* () {
for (let value of generator)
if (filter(value))
yield value;
};
return g;
}
which can be used to do what I want. 这可以用来做我想要的。
[...filtered (make_nums(), n => n > 1)] // => Array [ 2, 3 ]
But this is a very general function, which can be applied to every generator in the same way the filter
function can be applied to every Array
. 但这是一个非常通用的函数,它可以应用于每个生成器,就像
filter
函数可以应用于每个Array
。 So I tried to extend generators in general, but I do not understand how. 所以我试图扩展生成器一般,但我不明白如何。
The MDN documentation for generators suggests somehow that Generator.prototype
may exist, but it does not seem to exist. 生成器的MDN文档以某种方式表明
Generator.prototype
可能存在,但它似乎不存在。 When I try to define something in Generator.prototype
, I get the error 当我尝试在
Generator.prototype
定义一些东西时,我得到了错误
ReferenceError: Generator is not defined
ReferenceError:未定义Generator
How can I extend the built-in Generator
class? 如何扩展内置的
Generator
类?
With the traditional caveat that extending built-in prototypes is not necessarily the best idea, and that it's something to be done with caution, you can get the generator function prototype with 传统的警告说,扩展内置原型不一定是最好的想法,并且要谨慎做到这一点,你可以获得生成器函数原型
const genproto = Object.getPrototypeOf(function*(){});
With that you could add a filter()
capability: 有了它,你可以添加
filter()
功能:
Object.defineProperty(genproto, "filter", {
value: function*(predicate) {
for (let value of this())
if (predicate(value)) yield value;
}
});
And thus: 因此:
console.log([... function*() {
for (let i = 0; i < 10; i++) yield i;
}.filter(value => value % 2 === 0)
]);
will print [0, 2, 4, 6, 8]
. 将打印
[0, 2, 4, 6, 8]
。
To be clear: this answer is about extending the prototype for generator functions , not the generator objects themselves. 要明确:这个答案是关于扩展生成器函数的原型,而不是生成器对象本身。 Thus this will ensure that every generator function in the program can use that
.filter()
method and any other similar extension. 因此,这将确保程序中的每个生成器函数都可以使用
.filter()
方法和任何其他类似的扩展。
It turned out that I was confused about Generator
and Iterable
. 事实证明,我对
Generator
和Iterable
感到困惑。 I thought I had to extend Generator
, but it is actually sufficient to extend Iterable
. 我以为我必须扩展
Generator
,但实际上扩展Iterable
就足够了。 And the fact that Iterable
does not seem to be defined by JavaScript either, makes it easy to define it, to avoid problems with modifications of built-in prototypes. 事实上,
Iterable
似乎也没有被JavaScript定义,因此很容易定义它,以避免修改内置原型的问题。
This actually does what I tried to achieve. 这实际上做了我试图实现的目标。
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;
});
};
I can create Iterables
我可以创建
Iterables
make_nums = new Iterable(function* () { yield 1; yield 2; yield 3; });
can use them 可以使用它们
[...make_nums] // => Array [ 1, 2, 3 ]
and can filter them 并可以过滤它们
[...make_nums.filter(n => n > 1)] // => Array [ 2, 3 ]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.