!! javascript_产量! 产量! 生成器如何在JavaScript中工作。
!! 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.
该对象具有两个属性value
和done
。 该值包含要产生的值。 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
相关文章:

ACM 竞赛高校联盟 练习赛 第二场 BC
B. 题解: 枚举约数即可,判断n个数能否填约数的整数倍 #include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long LL; int main(){LL T, n, m;cin>>T;while(T--){cin>>n>>…

在一个数组中查找两个重复出现的数字
题目如下:现有一个数组长度为n1,里面存放有1到n-2,顺序不定,其中有两个数字出现了两次,现在要找出那两个数字。 例子A{2, 3, 1, 4, 5, 2, 4}, 这个数组长度为7,存放了1到5,但2和4出现…

React 组件生命周期
组件的生命周期可分成三个状态: Mounting:已插入真实 DOMUpdating:正在被重新渲染Unmounting:已移出真实 DOM 生命周期的方法有: componentWillMount 在渲染前调用,在客户端也在服务端。 componentDidMount : 在第一…

银行软件开发实习生_如何找到学生的软件开发人员实习生
银行软件开发实习生by Grazietta Hof由Grazietta Hof 如何找到学生的软件开发人员实习生 (How to find a Software Developer Internship as a student) Side note: Although this article is directed at students (because I am one so I can easily relate), I’m sure a l…

MAC OS X El CAPITAN 搭建SPRING MVC (1)- 目录、包名、创建web.xml
一、 下载STS(Spring Tool Suite) 官方地址:http://spring.io/tools/sts 下载spring tool suite for mac 最新版本。这个IDE是很不错的,其中spring插件已经配置好了。下载解压缩(一定要英文目录下)…

iOS小知识点记录
1>UITextField实现leftView: self.inputTextField [[UITextField alloc]initWithFrame:CGRectMake(10, 10, 200, 25)];self.inputTextField.delegate self;self.inputTextField.font [UIFont systemFontOfSize:15];self.inputTextField.placeholder " 想说点什么?…

Ant Design Pro 网络请求,视图绑定model并且渲染到页面 umi-request
封装网络请求,在service中新建接口,在model调用service,在视图绑定model并且得到网络请求的回调函数,获取网络请求的数据渲染到页面。 网络请求数据走向; 1.在utils/request.js 封装网络请求; /*** request 网络请求工具* 更详细的 api 文档: https://github.com/umijs…

2019机器学习比赛_2019顶尖的机器学习课程
2019机器学习比赛With strong roots in statistics, Machine Learning is becoming one of the most interesting and fast-paced computer science fields to work in. There’s an endless supply of industries and applications machine learning can be applied to to mak…

HTML5 canvas画图
HTML5 canvas画图 HTML5 <canvas> 标签用于绘制图像(通过脚本,通常是 JavaScript)。不过,<canvas> 元素本身并没有绘制能力(它仅仅是图形的容器) - 您必须使用脚本来完成实际的绘图任务。getCo…
排序算法7---快速排序算法
原理: 通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序的目的。 #include <stdio.h> #define MAXSIZE 9typedef stru…

dispatch callback ant design pro 网络请求回调函数
index.jsx 代码解析:在组件初次渲染时调用 model 中 命名空间为 a_models 的 getData 网络请求,传了一个patload 参数和 callback 回调函数过去,然后通过 this.setState ()更新视图的 state。 import { Form, Tabs,Affix, Button,Input,Table } from antd; import Re…

bigquery使用教程_如何使用Python和Google BigQuery构建机器人以自动执行您的笨拙任务...
bigquery使用教程Do you have repetitive tasks? Something that you do regularly, every week or even every day? Reporting might be one of your weekly or daily tasks. You query or ask for the data, and do some visualizations, then give it to your boss. What …

5S后返回首页
1 <!DOCTYPE html>2 <html>3 <head>4 <title>5S后返回首页</title> 5 <meta http-equiv"Content-Type" content"text/html; charsetgkb"/> 6 </head>7 <body>8 <h2>操作成功</h2>…
TypeScript 1
TypeScript 的由来 TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准。 TypeScript 由微软开发的自由和开源的编程语言。 TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何…

大龄屌丝自学笔记--Java零基础到菜鸟--028
泛型,for循环增强应用,静态导入,可变参数,asList() 1、泛型 约束了数据类型,格式为 <数据类型>,如:ArrayList<int> aListnew ArrayList<int>(); 泛型通配符:<?…

c# typescript_在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法
c# typescriptby Leonardo Carreiro莱昂纳多卡雷罗(Leonardo Carreiro) 在任何IDE中从C#,Java或Python代码获取TypeScript接口的简单方法 (The easy way to get TypeScript interfaces from C#, Java, or Python code in any IDE) Who has never experi…

js里的document对象大全(DOM操作)
什么是DOM document object model 的简称,意思为文档对象模型。主要用来对文档中的html节点进行操作。 Dom的操作简单示例: <div id"t1"><div><input type"file" /> <input type"button" value"…

【制作镜像】BCEC制作镜像
如要制作的新镜像已存在标准版本镜像,即linux发行版本相同(此处指CentOS6.5 64位),可利用BCEC制作。 在BCEC创建centos6.5系统的可联外网的虚机,ssh到此虚机,用yum方式安装所需的功能: yum&…

Ant Design Pro 组件事件绑定 Input onChange
Input 组件的 onChange 事件绑定语法 render() {this.shop_change e > {const { value } e.target;console.log(shop_change,value)};return (<Input placeholder"" onChange{this.shop_change}></Input>)}

软件访问转向本地_我是如何从完整的初学者转向软件开发人员的,以及如何做到的...
软件访问转向本地by Madison Kanna麦迪逊卡纳(Madison Kanna) 我是如何从完整的初学者转向软件开发人员的,以及如何做到的 (How I went from complete beginner to software developer — and how you can too) Two years ago, I was right where you are today.两…

.NET笔试题集(五)
转载于:http://www.cnblogs.com/ForEvErNoME/archive/2012/09/15/2684938.html 1.什么是受管制的代码? 答:unsafe:非托管代码。不经过CLR运行。 2.net Remoting 的工作原理是什么? 答:服务器端向客户端发送…

devServer proxy跨域 设置代理 proxy
概念 什么是同源策略 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。 所谓同源是指…

转帖 开源游戏服务器调研
汇总贴 2013年优秀的开源引擎与开源游戏项目 http://mobile.51cto.com/aengine-431122.htm http://www.oschina.net/search?scopeproject&q%E6%89%8B%E6%B8%B8 当前的几种开源游戏服务端介绍 http://www.oschina.net/question/1986738_224669 用户贴,使用过后…

websockets_如何将WebSockets与AWS API Gateway和Lambda一起使用来构建实时应用程序
websocketsby Janitha Tennakoon通过詹妮莎特纳库恩 如何将WebSockets与AWS API Gateway和Lambda一起使用来构建实时应用程序 (How to build real-time applications using WebSockets with AWS API Gateway and Lambda) Recently AWS has announced the launch of a widely-r…

JS对象转URL参数
代码: /*** param 将要转为URL参数字符串的对象* key URL参数字符串的前缀* encode true/false 是否进行URL编码,默认为true* idx ,循环第几次,用&拼接* return URL参数字符串*/ var urlEncode (param,idx, key, encode)> {console.log(idx,idx…

Windows下Redis如何永久更改密码
公司使用的是Spring-session-redis 需要给Redis配置一个密码 本来我配置密码的方法是 先打开Redis服务 在采用 命令 CONFIG SET requirepass "密码" AUTH 密码 但是这样配置完密码之后再重启Redis服务密码会重置 也就是说每次打开Redis服务都要重新再配置一下密码 …

CEGUI-----动画
Animation XML files. <AnimationDefinition> <Affector name‘要被改变的属性名’ interpolator‘关键帧之间平滑过度的数值’> //specifies the name of a property that will be affected (have its value changed) as part of the animation <KeyFrame>…

react hooks使用_如何使用Hooks将React类组件转换为功能组件
react hooks使用by Balaganesh Damodaran通过Balaganesh Damodaran 如何使用Hooks将React类组件转换为功能组件 (How to convert React class components to function components using Hooks) Over the course of the past month, I’ve spent a lot of time working with Re…

[精]Odoo 8.0深入浅出开发教程-模块开发基础
參考资料点击这里.构建Odoo模块模块组成业务对象业务对象声明为Python类, 由Odoo自己主动加载.数据文件XML或CSV文件格式, 在当中声明了元数据(视图或工作流)、配置数据(模块參数)、演示数据等.Web控制器处理Web浏览器发来的requests.静态web数据Web用到的图像, CSS或JavaScrip…

Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)...
1. 使用字符流缓冲流的特殊功能 [ newLine() / readLine() ] 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 数据源: a.txt -- 读取数据 -- 字符转换流 -- InputStreamReader -- FileReader -- BufferedReader 目的地:…