yield生成字典_JavaScript中的生成器何时应使用yield和yield

yield生成字典

Even five years after the release of ES6, there are still some aspects of it that not every JavaScript developer is familiar with. These are usually the sides of it that are not used in every day code. That is fine. But even seemingly useless knowledge is never actually useless. This ES6 feature that no one knows about might be the elegant solution to that one tricky problem that has been causing you headaches.

即使在ES6发布之后的五年,它的某些方面仍然不是每个JavaScript开发人员都熟悉的。 这些通常是每天代码中未使用的方面。 那样就好。 但是,即使是看似无用的知识也永远不会真正无用。 这个没人知道的ES6功能可能是解决一个棘手问题的绝佳解决方案,该问题一直困扰着您。

One of these features is generators. Even though extremely powerful, generators are mostly buried deep inside useful libraries, but rarely used in the day-to-day programming. Still, most of us have at least a vague idea of what the yield keyword does. Can you say that much of yield*?

这些功能之一是发电机。 尽管功能非常强大,但生成器大多埋在有用的库中,但很少在日常编程中使用。 尽管如此,我们大多数人对yield关键字的作用至少有一个模糊的想法。 你能说多少yield*吗?

发电机 (Generators)

These two keywords, yield and yield*, appear in the context of generators, and can’t be understood outside of it.

这两个关键字yieldyield*出现在生成器的上下文中,在其外部无法理解。

A generator is an object that can produce a sequence of values but can also be iterated over like an array. To use more precise terms, a generator is an object that implements the iterator and the iterable protocols.

生成器是一个对象,它可以产生一个值序列,但也可以像数组一样进行迭代。 为了使用更精确的术语,生成器是实现迭代器和可迭代协议的对象。

Concretely, because generators are iterators, we can do this:

具体来说,因为生成器是迭代器,所以我们可以这样做:

const generator = ... // we will see later how to create a generatorgenerator.next();
generator.next();
generator.next();
generator.next();

And because they also are iterables we can do this:

而且因为它们也是可迭代的,所以我们可以这样做:

const generator = ... // a bit of patiencefor (const value of generator) {
// ...
}

As you might have guessed from the part I have left out, yield intervenes in the creation of a generator.

正如您可能从我遗漏的部分中猜到的那样, yield干预了生成器的创建。

发电机功能 (Generator Functions)

Generators are created using generator functions. These functions are declared using function* or function *.

生成器是使用生成器函数创建的。 这些函数使用function*function *

In a generator function you define the values that are going to be returned when the next function is called on the generator. To do so, you use the keyword yield :

在生成器函数中,您定义在生成器上调用next函数时将要返回的值。 为此,可以使用关键字yield

function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}const generator = generatorFunction();generator.next(); // { value: 1, done: false }
generator.next(); // { value: 2, done: false }
generator.next(); // { value: 3, done: false }
generator.next(); // { value: undefined, done: true }

When the next method is called, the generator is executed until the next yield expression and returns the specified value.

调用next方法时,将执行生成器,直到下一个yield表达式并返回指定的值。

yield is actually a two-way street. You can also use it to pass value to your generator. Let’s say you want a generator that can receive some value as input to then return this value every time the next method is called. You would do it by using yield like this:

yield实际上是一条双向道路。 您还可以使用它来传递给生成器。 假设您希望生成器可以接收一些值作为输入,然后在每次调用next方法时都返回此值。 您可以通过使用yield来做到这一点:

function* generatorFunction() {
const a = yield; while(true) {
yield a;
}
}const generator = generatorFunction();generator.next();
generator.next(1); // { value: 1, done: false }
generator.next(); // { value: 1, done: false }
generator.next(); // { value: 1, done: false }

You might find the first call generator.next() weird but it is not a mistake. As said earlier, when the next function is called, the generator is executed until the next yield expression. The first time we call it on our brand new generator, it runs until the first yield, has nothing to return so waits there. The second time, we call it with a value, it initialises the variable a to this value and goes to the next yield, where it returns a, in our case 1. For every call afterwards, it yields the value of a.

您可能会发现第一个调用generator.next()很奇怪,但这不是一个错误。 如前所述,调用next函数时,将执行生成器,直到下一个yield表达式为止。 第一次在全新的发电机上调用它时,它将一直运行到第一个yield为止,没有任何回报,因此请在那里等待。 第二次,我们把它叫做一个值,它初始化的变量a该数值和进入下一个yield ,它返回a ,在我们的例子1 。 对于每一个电话之后,它产生的值a

让* (yield*)

What about yield*? yield* is also being used in generator functions, but of course to achieve something different.

yield*呢? yield*也用于生成器函数中,但是当然可以实现一些不同。

Imagine you want to create a generator that returns the Fibonacci numbers. As a reminder, Fibonacci numbers are defined as follows:

假设您要创建一个返回斐波那契数字的生成器。 提醒一下,斐波那契数定义如下:

  • the first one is 0

    第一个是0
  • the second one is 1

    第二个是1
  • after this each number is the sum of the two previous ones

    在此之后,每个数字是前两个数字的和

In other words: F(0) = 0; F(1) = 1; ... F(n) = F(n-1) + F(n-2);

换句话说: F(0) = 0; F(1) = 1; ... F(n) = F(n-1) + F(n-2); F(0) = 0; F(1) = 1; ... F(n) = F(n-1) + F(n-2);

How would you create a generator generating these values? You would probably want to do it recursively.

您将如何创建一个生成这些值的生成器? 您可能需要递归地进行操作。

function* fibonacciGeneratorFunction() {
yield 0;
yield 1;
???
}const fibonacciGenerator = fibonacciGeneratorFunction();

We actually want to yield the values of an other generator, inside our generator. This is where yield* comes in:

我们实际上想在我们的生成器内部产生另一个生成器的值。 这是yield*来源:

function* fibonacciGeneratorFunction(a = 0, b = 1) {
yield a;
yield* fibonacciGeneratorFunction(b, b + a);
}const fibonacciGenerator = fibonacciGeneratorFunction();fibonacciGenerator.next(); // { value: 1, done: false }
fibonacciGenerator.next(); // { value: 1, done: false }
fibonacciGenerator.next(); // { value: 2, done: false }
fibonacciGenerator.next(); // { value: 3, done: false }
fibonacciGenerator.next(); // { value: 5, done: false }

yield* isn’t only used in recursive cases. It generally enables you to delegate to another generator. A simple example from the MDN web docs is:

yield*不仅用于递归情况。 通常,它使您可以委派给另一个生成器。 MDN Web文档中的一个简单示例是:

function* g1() {
yield 2;
yield 3;
yield 4;
}
function* g2() {
yield 1;
yield* g1();
yield 5;
}
const iterator = g2();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: 5, done: false}
console.log(iterator.next()); // {value: undefined, done: true}

I hope this article unveiled the mystery of yield and yield*. While both are used in the context of generator, yield and yield* enable you to generate values differently. The first one lets you return values directly or provide them to your generator. The second one lets you delegate the value generation to another generator.

我希望本文揭开了yieldyield*之谜。 虽然两者都在生成器的上下文中使用,但是yieldyield*使您能够不同地生成值。 第一个允许您直接返回值或将其提供给生成器。 第二个让您将值生成委托给另一个生成器。

翻译自: https://medium.com/javascript-in-plain-english/generators-in-javascript-when-should-i-use-yield-and-yield-a5dbea6ad625

yield生成字典

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值