!! javascript

by Ashay Mandwarya ?️??

由Ashay Mandwarya提供吗?

产量! 产量! 生成器如何在JavaScript中工作。 (Yield! Yield! How Generators work in JavaScript.)

If the title doesn’t already give a hint, we will be discussing generators in this piece.

如果标题还没有提示,我们将在本文中讨论生成器。

Before going into generators let’s revise some basics about functions.

在进入生成器之前,让我们修改一些有关函数的基础知识。

  • In JavaScript, functions are a set of statements that perform a task and return some value ending the function.在JavaScript中,函数是一组语句,它们执行任务并返回一些结束函数的值。
  • If you call a function, again and again, it will execute all the statements again and again.如果一次又一次调用一个函数,它将一次又一次地执行所有语句。
  • Arrows once left from the bow cannot be stopped — they only either hit or miss. The same way a function once called cannot be stopped, it will run, return a value, throw an error and then will stop after executing all the statements.一旦从弓上离开,箭头就无法停止-它们只能命中或错过。 无法调用曾经调用过的函数的方法相同,它将运行,返回值,抛出错误,然后在执行所有语句后停止。

We only need to keep in mind these 3 points to understand generators.

我们只需要记住这三点就可以了解生成器。

发电机 (Generators)

A generator is a special type of function which can stop its execution midway and then start from the same point after some time. Generators are a combination of functions and iterators. This is a bit of a confusing statement but I will make sure by the end of the article this line will be clear.

生成器是一种特殊的函数,可以在中途停止执行,然后在一段时间后从同一点开始执行。 生成器是功能和迭代器的组合。 这有点令人困惑,但是我将确保在本文结尾时这一行将是清楚的。

For clarity, consider playing a game and suddenly mom calls for some work. You pause the game, help her, then resume playing again. It is the same with generators.

为了清楚起见,考虑玩游戏,突然妈妈给他打电话去找工作。 您暂停游戏,帮助她,然后重新开始游戏。 发电机也一样。

An iterator is an object which defines a sequence and potentially a return value upon its termination. — MDN.

迭代器是一个对象,它定义序列,并在终止时定义返回值。 — MDN。

Iterators in themselves are a huge topic and are not the aim of this article.

迭代器本身是一个巨大的话题,而不是本文的目的。

基本语法 (Basic Syntax)

Generators are defined as a function with an asterisk(*) beside the function.

生成器被定义为在函数旁边带有星号(*)的函数。

function* name(arguments) {   statements}

name — The function name.

name —函数名称。

arguments — Arguments for the function.

arguments —函数的参数。

statements — The body of the function.

语句—函数的主体。

返回 (Return)

A function can return almost anything ranging from a value, object or another function itself. A generator function returns a special object called the generator object (not entirely true). The object looks like the snippet below

一个函数几乎可以返回任何值,从值,对象或另一个函数本身开始。 生成器函数返回一个特殊的对象,称为生成器对象( 不完全为true )。 该对象看起来像下面的代码片段

{   value: value,  done: true|false}

The object has two properties value and done . The value contains the value to be yielded. Done consists of a Boolean (true|false) which tells the generator if .next() will yield a value or undefined.

该对象具有两个属性valuedone 。 该值包含要产生的值 Done由布尔值(true | false)组成,该布尔值告诉生成器.next()将产生值还是未定义。

The above statement will be difficult to digest. Let's change that with an example.

以上陈述将难以理解。 让我们用一个例子来改变它。

function* generator(e) {  yield e + 10;  yield e + 25;  yield e + 33;}var generate = generator(27);
console.log(generate.next().value); // 37console.log(generate.next().value); // 52console.log(generate.next().value); // 60console.log(generate.next().value); // undefined

Let’s understand the mechanics of the above code line by line.

让我们逐行了解上述代码的机制。

lines 1–5: Lines 1–5 define the generator having the same name with an argument e. Inside the body of the function, it contains a bunch of statements with the keyword yield and some operation is done after that.

第1至5 行:第1至5行使用参数e定义了具有相同名称的生成器。 在函数主体内部,它包含一堆带有关键字yield的语句,然后执行一些操作。

line 6: Line 6 assigns the generator to a variable called generate.

第6行:第6 行将生成器分配给一个名为generate的变量。

lines 8–11: These lines call a bunch of console.log each calling the generator chained to a next method which calls for the value property of the generator object.

第8-11行:这些行调用一堆console.log每行调用生成器,该生成器链接到next方法,该方法调用生成器对象的value属性。

Whenever a generator function is called upon, unlike normal functions it does not start execution right away. Instead, an iterator is returned (the actual reason * is used by a generator. It tells JS that an iterator object is to be returned). When the next()method of the iterator is called, the execution of the generator starts and executes until it finds the first yield statement. At this yield point the generator object is returned, the specifications of which are already explained. Calling the next() function again will resume the generator function until it finds another yield statement and the cycle returns till all yields are exhausted.

每当调用生成器函数时,与普通函数不同,它不会立即开始执行。 而是返回一个迭代器( 生成器使用了实际原因*。它告诉JS要返回一个迭代器对象 )。 当调用迭代器的next()方法时,生成器的执行开始并执行,直到找到第一个yield语句为止。 在此屈服点,将返回生成器对象,其说明已经说明。 再次调用next()函数将恢复生成器函数,直到找到另一个yield语句,然后循环返回直到所有的yields都用完为止。

After this point if next is called it returns the generator object with value undefined.

在此之后,如果调用next ,它将返回值未定义的生成器对象。

Now let’s try yielding another generator function from the original generator and also a return statement.

现在,让我们尝试从原始生成器生成另一个生成器函数,以及一个return语句。

A return statement in a generator will make the generator finish its execution like every other function. The done property of the generator object will be set to true and the value returned will be set to the value property of the generator object. All other yields will return undefined.

生成器中的return语句将使生成器像其他所有函数一样完成其执行。 生成器对象的done property将设置为true ,返回的value将设置为生成器对象的value属性。 所有其他yields将返回undefined

If an error is thrown then also the execution of the generator will stop, yielding a generator itself.

如果抛出错误,则生成器的执行也会停止,从而生成生成器本身。

For yielding a generator we need to specify an * against the yield so as to tell JS that a generator is yielded. The yield* delegates to another generator function — that is the reason we can yield all the values of the generator2 function using the generate.next() of the original generator function. The first value yielded is from the first generator function and the last two yielded values are generated by the generator function but yielded by the original generator.

为了yielding一个生成器,我们需要在yield上指定一个*,以便告诉JS生成了一个生成器。 该yield*委托给另一个发生器功能-这是我们能原因yield的所有值generator2使用功能generate.next()原发电机的功能。 所述第一值yielded与所述第一发生器函数和最后两个yielded由发生器函数生成的值,但是yielded由原始发生器。

优点 (Advantages)

Lazy loading

延迟加载

Lazy loading is essentially value evaluation only when there is a need for it. As we will see in a coming example, we can actually do it with generators. We might only yield the values when needed and not all at the same time.

延迟加载实质上仅在需要时才是值评估。 正如我们将在接下来的示例中看到的那样,我们实际上可以使用生成器来做到这一点。 我们可能只在需要时才产生值,而不是同时产生所有值。

The below example is from another example in this article and it generates infinite random numbers. Here we can see we can call as many next() as we want and not get all the values it is producing. Only the needed ones.

下面的示例来自本文的另一个示例,它生成无限的随机数。 在这里,我们可以看到可以调用任意数量的next() ,而不必获取它正在生成的所有值。 只有需要的。

function * randomize() {  while (true) {let random = Math.floor(Math.random()*1000);    yield random;  }}
var random= randomize();
console.log(random.next().value)

Memory Efficient

高效记忆

As we can deduce from the above example, generators are extremely memory efficient. As we want the values only according to need, we need very less storage for storing those values.

从上面的示例可以推断出,生成器的存储效率极高。 因为我们只想根据需要来获取值,所以我们只需要很少的存储空间来存储这些值。

陷阱 (Pitfalls)

Generators are extremely useful but also have their own pitfalls too.

生成器非常有用,但也有其自身的陷阱。

  • Generators don’t provide random access like arrays and other data structures. As the values are yielded one by one on call we cannot access random elements.

    生成器不提供像数组和其他数据结构这样的随机访问 。 由于这些值是在调用时一对一产生的,因此我们无法访问随机元素。

  • Generators provide one-time access. Generators don’t allow you to iterate the values again and again. Once all the values are exhausted we have to make a new Generator instance to iterate all the values again.

    生成器提供一次性访问。 生成器不允许您一次又一次地迭代这些值。 一旦所有值用尽,我们必须创建一个新的Generator实例以再次迭代所有值。

为什么我们需要发电机? (Why do we need Generators?)

Generators provide a wide variety of uses in JavaScript. Let’s try to recreate some ourselves.

生成器在JavaScript中提供了多种用途。 让我们尝试重建自己。

Implementing Iterators

实现迭代器

An iterator is an object that enables a programmer to traverse a container -Wikipedia

迭代器是使程序员能够遍历容器的对象-Wikipedia

We will print all the words present in a string using iterators. Strings are iterators too.

我们将使用迭代器打印字符串中存在的所有单词。 字符串也是迭代器。

Iterators

迭代器

const string = 'abcde';const iterator = string[Symbol.iterator]();console.log(iterator.next().value)console.log(iterator.next().value)console.log(iterator.next().value)console.log(iterator.next().value)console.log(iterator.next().value)

Here’s the same thing using generators

这与使用生成器相同

function * iterator() {yield 'a';yield 'b';yield 'c';yield 'd';yield 'e';}for (let x of iterator()) {console.log(x);}

Comparing both the methods, it is easy to see that with the help of generators we can do it with less clutter. I know it is not a very good example but enough to prove the following points:

比较这两种方法,不难发现,借助发生器,我们可以减少杂波。 我知道这不是一个很好的例子,但足以证明以下几点:

  • No implementation of next()

    没有实现next()

  • No [Symbol.iterator]() invocation

    没有[Symbol.iterator]()调用

  • In some cases, we even need to set the object.done property return value to true/false using iterators.

    在某些情况下,我们甚至需要使用迭代器将object.done属性的返回值设置为true / false。

异步等待〜承诺+生成器 (Async-Await ~ Promises+Generators)

You can read my previous article about Async/Await if you want to learn about them, and check out this for Promises.

你可以阅读我以前关于异步/等待的文章,如果你想了解他们,并检查了这对承诺。

Crudely, Async/Await is just an implementation of Generators used with Promises.

粗略地讲,异步/等待只是与Promises一起使用的Generators的实现。

Async-Await

异步等待

async function async-await(){let a=await(task1);console.log(a);
let b=await(task2);console.log(b);
let c=await(task3);console.log(c);
}

Promises+Generators

承诺+产生者

function * generator-promise(){let a=yield Promise1();console.log(a);let b=yield Promise1();console.log(b);let c=yield Promise1();console.log(c);
}

As we can see, both produce the same result and almost in a similar fashion too. It’s because the Async/Await mechanism is loosely based on a combination of generators and promise. There is a lot more to Async/Await than shown above, but just for showing the use of a generator, we can consider this.

如我们所见,两者都产生相同的结果,并且几乎也以相似的方式产生。 这是因为Async / Await机制宽松地基于生成器和Promise的组合。 除了上面显示的内容外,Async / Await还有很多其他功能,但是仅出于展示生成器的用途,我们可以考虑一下。

无限数据结构 (Infinite Data Structure)

The heading might be a little misleading, but it is true. We can create generators, with the use of a while loop that will never end and will always yield a value.

标题可能有点误导,但这是事实。 我们可以使用while循环来创建生成器,该循环永远不会结束,并且总是会产生一个值。

function * randomize() {  while (true) {let random = Math.floor(Math.random()*1000);    yield random;  }}var random= randomize();while(true)console.log(random.next().value)

In the above snippet, we create an infinite generator, which will yield a random number on every next() invocation. It can be called as an infinite stream of random numbers. This is a very basic example.

在上面的代码片段中,我们创建了一个无限生成器,它将在每次next()调用时产生一个随机数。 可以将其称为无限随机数流。 这是一个非常基本的例子。

结论 (Conclusion)

There is yet a lot to be covered about generators, and this was just an introduction to the topic. Hope you learned something new and the article was easy to understand.

关于生成器,还有很多要讨论的内容,而这仅仅是该主题的介绍。 希望您学到了新东西,并且这篇文章很容易理解。

Follow me and applaud!

跟着我鼓掌!

翻译自: https://www.freecodecamp.org/news/yield-yield-how-generators-work-in-javascript-3086742684fc/

!! javascript

!! javascript_产量! 产量! 生成器如何在JavaScript中工作。相关推荐

  1. 如何在JavaScript中实现链接列表

    If you are learning data structures, a linked list is one data structure you should know. If you do ...

  2. regexp 好汉字符串_如何在JavaScript中使用RegExp确认字符串的结尾

    regexp 好汉字符串 by Catherine Vassant (aka Codingk8) 由凯瑟琳·瓦森(Catherine Vassant)(又名Codingk8) 如何在JavaScrip ...

  3. javascript案例_如何在JavaScript中使用增强现实-一个案例研究

    javascript案例 by Apurav Chauhan 通过Apurav Chauhan 如何在JavaScript中使用增强现实-一个案例研究 (How to use Augmented Re ...

  4. java+script+当前日期_如何在JavaScript中获取当前日期?

    如何在JavaScript中获取当前日期? #1楼 您可以使用扩展了 Date对象的Date.js库,从而可以使用.today()方法. #2楼 如果您想对日期格式进行更多的粒度控制,我强烈建议您查看 ...

  5. 如何在Javascript中访问对象的第一个属性?

    本文翻译自:How to access the first property of an object in Javascript? Is there an elegant way to access ...

  6. 如何在JavaScript中实现堆栈和队列?

    本文翻译自:How do you implement a Stack and a Queue in JavaScript? What is the best way to implement a St ...

  7. 如何在JavaScript中比较数组?

    本文翻译自:How to compare arrays in JavaScript? I'd like to compare two arrays... ideally, efficiently. 我 ...

  8. 如何在javascript中使用多个分隔符分割字符串?

    如何在JavaScript中使用多个分隔符拆分字符串? 我正在尝试在逗号和空格上进行拆分,但是AFAIK,JS的拆分功能仅支持一个分隔符. #1楼 对于那些想要在拆分功能中进行更多自定义的人,我编写了 ...

  9. 如何在JavaScript中验证电子邮件地址

    如何在JavaScript中验证电子邮件地址? #1楼 与squirtle相比 ,这是一个复杂的解决方案,但是在正确验证电子邮件方面做得非常出色: function isEmail(email) { ...

最新文章

  1. UNIX环境高级编程 第12章 线程控制
  2. java messagebox 关闭_wince/WinForm下实现一个自动关闭的MessageBox
  3. ctf图片隐写之修改图片高度
  4. kylin安装mysql_源码安装mysql
  5. 16-CoreData之多表关联(存储自定义数据模型)
  6. Java 开发人员 2019 生态系统信息图
  7. C++静态联编与动态联编
  8. C#控件的闪烁问题解决方法总结
  9. 【汇编语言与计算机系统结构笔记07】条件码,比较、测试、条件跳转与条件转移指令,结合微体系结构与流水的说明
  10. JAVA经典集合框架学习笔记——HashMap的底层实现原理
  11. 电脑右下角自动弹出窗口(弹窗)
  12. 【Cubase11】音乐工作站:宿主软件 - 基础入门笔记
  13. js实现商城特效---鼠标移入图片放大
  14. 一个简单的显示阴历的日历。
  15. 自监督学习经典之作:DINO
  16. Java电商平台-电商订单系统全解析
  17. Openstack 高可用部署(Ocata版)
  18. 怎么把html表格转化为excel,导出html到excel表格数据格式-如何将html转换成excel
  19. Windows版本,OS内核版本,Windows SDK之间的关系(附 :Windows纯净系统下载以及更新)
  20. 将wordpress博客转移至新虚拟主机

热门文章

  1. Vue 增加动态路由功能 【在原有系统上增加】
  2. 编写spring应用
  3. java maven项目使用sonar审核代码
  4. Oracle Study之--ORA-12537(TNS:connection closed) 错误案例
  5. 前端部分面试题整理,欢迎补充
  6. MathType在手,公式不求人!
  7. sdut AOE网上的关键路径(spfa+前向星)
  8. IIS日志清理CMD版,VBS版,JS版,WSH版
  9. 云计算之Docker介绍
  10. 比较v-bind和v-model