generator-yield到底是个啥
咱们通过上篇文章的简单介绍,已经了解到yield是放弃执行,放弃现在继续执行的权利,把权利让给别人,什么时候想继续执行的时候,再调一次就好。接下来咱们说两件事,就是yield是一个很有意思的东西,它可以传参,也可以有返回值。(提醒:接下来的东西略微有点难懂,大家不要过于纠结和较真,后面应用的时候,很多东西就自然通顺了)
一、yield可以传参
先来一个函数
function *show() {
alert('a'); let a = yield;
alert(a); alert('b');
} let gen = show(); gen.next(12);
gen.next(5);
通过函数我们可以看到,定义a接收了yield传进来的参数,现在请大家和我玩个游戏,猜猜看a是几
好了,不卖关子了,咱们执一下看看
那么现在反过来就有一个问题了,可能有些人会说,等会,我有点看不明白了,我怎么觉得应该是12呢,怎么回事呢?
好,简答的说一说为什么是5,这个实际上来说是yield里面特别好玩的一件事,大家允许我用一个小小的方法(用一张图来说明)
从上面的图上,我们可以看到画红框的地方,执行的是我用红笔圈起来的这部分代码,画绿框的地方,执行的是用绿笔圈起来的代码
我们把它简答的看做两个过程,第一个过程传进去的参数是12,第二个过程传递进去的参数是5,所以我们的a接收到的是我们第二个过程里传进去的5,没问题吧,当然还是那句话,别较真,认真你就输了,大家都懂的哈
那么所以通过yield传参的时候,第一个next是废的,传什么都不好使,传什么都白传,这个时候大家可能会问了,那我想给第一个过程传参,该怎么办呢?你说怎么办,不就是我们过去的传参方法嘛,我们传一个num1,一个num2,然后接收一下,咱试试哈
function *show(num1, num2) {
alert(`${num1}, ${num2}`);
alert('a'); let a = yield;
alert(a); alert('b');
} let gen = show(99, 88); gen.next(12);
gen.next(5);
这样运行的话,可以正常接收我们传进来的参数
而通过这个过程,我们可以看到,第一个next对于传参来说,是废的,没办法给yield传参的,想给第一个过程传递参数,就得像正常函数一样,通过函数(参数)的形式来
二、yield可以返回
咱们刚刚说了yield的第一个功能是可以往里面传东西,下面我们说一说yield的另一个功能,可以往外吐东西(返回)
咱们在上面把一个大的generator函数划分为几个过程,通过yield来分割这几个过程,我们可以理解为中间结果
举个最简单的例子,就像我做菜一样,当然我这人不会做菜,连锅都能糊了,可好玩了,有时间再和大家慢慢扯哈
就拿做菜来说,我们可以分为几个步骤:洗菜、切菜、炒菜
我们可以认为,在最开始输入了刚买回来的菜,也相当于我们函数的参数,接下来的每一步都有一个半成品(刚买回来的菜),它也就相当于我们下一步的输入,最后变成一盘炒好的菜。说白了,在这个函数里,每一步都会有一个中间结果,也算是中间的输入。
从第一步的yield可以传参到第二步的yield有个中间结果,下面我们看一看yield是如何返回的
function *show() {
alert('a'); yield 12; alert('b'); } let gen = show(); let res1 = gen.next();
console.log(res1); //{value: 12, done: false} let res2 = gen.next();
console.log(res2); //{value: undefined, done: true}
咱们还是和刚才一样,定义一个generator函数,定义两个过程,将next函数的返回值打印出来之后可以看到,第一个过程中返回了
{value: 12, done: false},第二个过程返回了{value: undefined, done: true},在第一个过程里,value是12,done是false,done是完成的意思,因为第一个过程并不是函数结束,所以返回的是false,而第二个返回值中,value为什么是undefined呢?
原因很简单,咱们在上面的切菜图上说的很明白了,这个阶段是咱们函数的最后一道工序,最后一道工序就没有yield了,所以也就没有返回值了,想返回东西的话,就只能用return来返回。
请允许我用一个更俗的例子来把这事说的更清楚。
三、yield到底是个啥
咱们用伪代码定义了一个generator函数,咱名字就叫炒菜,最初的参数是刚从菜市场买回来的菜,第一步完成洗菜的过程,然后通过yield把洗好的菜传递给下一个过程,下一个人拿到干净的菜之后把它切成块,切成丝,再通过yield传给下一个人,然后下一个人拿到切好的菜之后,就可以炒了,最后我们得到熟的菜,把它return出去。下面咱们画一画,帮助大家更好的理解
首先蓝色框里画的是第一个过程,红色框是第二个过程,绿色框是第三个过程,而中间的yield就相当于隔在他们中间的“墙”,“墙”之前是一个过程,之后是另一个过程。在过程一的输入是(菜市场买回来的菜),做了一些工作之后,把洗好的菜(中间结果)返回出去,在“墙”的那边,得到的是我们返回的干净的菜,然后咣咣咣一顿切之后,得到了切好的菜(中间结果),有了中间结果之后,在“墙”的那一边有人得到了我们的中间结果,然后拿去炒,得到熟的菜,最终的结果return出去。总的来说,最初的东西走参数,最终的结果走return,其实generator咱要这么说的话,也不难,就是中间步骤可以返回出去,那边怎么着怎么着,反正就这点事。
相信通过上面有些神经病的讲解之后,相信大家应该比较彻底的了理解了generator以及它的yield,还是那句话,较真你就输了。
接下来呢,咱们要干件事了,既然明白了,既然理解了,接下来趁热打铁,咱们用一用它,中国有句古话“光说不练....”,嗯,大家都懂,我就不多说了,咱们来用一用它,看看它能干啥,generator其实在很大程度上和Promise很像,都是用来解决异步操作相关问题的。废话不多说,咱们在下一篇文章中直接拿来玩,感兴趣的话,可以继续关注我。
generator-yield到底是个啥的更多相关文章
- Generator & yield write in sync way
Generator & yield write in sync way var p = new Promise(function(resolve, reject){ setTimeout(fu ...
- Generator yield语法和 co模块
Generator yield 语法使用,也叫生成器,实际上就是多个异步按顺序执行 1.下面是一个读取两个文件的例子 const fs = require('fs'); const readFile ...
- 异步编程的上下文与操作符--await/async generator/yield
上下文的保存机制: 1.保存到异步类型中:promise & future & closure & observable: 2.栈帧保存:其它保存机制: 3.保存到服务提供方的 ...
- ES Next & Arrow function & Promise & Iterator & Generator yield & Async Await
ES Next & Arrow function & Promise & Iterator & Generator yield & Async Await co ...
- 生成器(generator,yield),next,send
#生成器 def generator(): for i in range(200): yield '哇哈哈%s' %i g = generator() #调用生成数函数,接受作用 ret = g.__ ...
- python3----生成器generator(yield)
# 列表推导式a = [i for i in range(100) if not(i % 2) and (i % 3)]print(a)# 字典推导式b = {i: i % 2 == 0 for i ...
- Python: generator, yield, yield from 详解
1.Generator Expressions 生成器表达式是用小括号表示的简单生成器标记法: generator_expression ::= "(" expression co ...
- JS Generator yield
function show() { console.log('a') console.log('b') } show() // 普通函数 function *show2() { console.log ...
- Python高级语法之:一篇文章了解yield与Generator生成器
Python高级语法中,由一个yield关键词生成的generator生成器,是精髓中的精髓.它虽然比装饰器.魔法方法更难懂,但是它强大到我们难以想象的地步:小到简单的for loop循环,大到代替多 ...
- Python yield 使用浅析
转载来自: http://www.ibm.com/developerworks/cn/opensource/os-cn-python-yield/ 初学 Python 的开发者经常会发现很多 Pyth ...
随机推荐
- JavaWeb_常用功能_01_文件上传
一个功能完善的JavaWeb应用,必不可少的一个功能就是文件的上传.无论是用户的头像等,还是用户需要上传的一系列资料,都是通过文件的上传功能实现的. 目前我们实现网站中关于文件的上传功能时,常用的是a ...
- type为number的input标签输入小数的方法
纠结了一段时间都没找出方法,最后灵光一现想出这个方法,没想到测试下果然成功了! 看目前网上几乎很难找到相对应的解决方法,所以这里分享出来,如果有更佳方法欢迎提出. 方法如下: <input ty ...
- 关于自动化与vTable两种暴露接口的区别-1未完......
COM组件有两种暴露组件接口的方式,一种是以虚拟列表的方式暴露:一种就是自动化方式. 虚拟列表(VTable): COM组件将自己所有的方法的地址以一个虚拟表的方式存放在一起,这个虚拟表是一种结构,有 ...
- Python解决中文字符的问题
from __future__ import unicode_literals print(type("test")) #<type 'unicode'> Chinat ...
- 在Windows下编译WebRTC
前言 这篇文章的目的在于为你节省生命中宝贵的10小时(甚至更多),或者浪费你10分钟.作为Google更新频繁的大型跨平台基础库,WebRTC的编译一直被人称为噩梦.如果恰巧你偏要在Windows下编 ...
- 用遗传算法解决TSP问题
浅谈遗传算法:https://www.cnblogs.com/AKMer/p/9479890.html Description \(小m\)在踏上寻找\(小o\)的路程之后不小心碰到了大魔王\(fat ...
- 排成一行的li之间的间隙问题
现象 对于ul下li排成一行的布局(即li的display由list-item设为inline-block): 情况1 如果这些li在书写的时候有换行或者有空格,且ul本身的font-size不为0, ...
- C# 性能总结
尽量使用using语句块和finally (实现IDisposable) 尽量使用单个大程序集而不是多个小程序集 (使用NGen.exe) 使用sealed关键字 权衡虚函数 使用弱引用
- CUDA V9.2 sample编译问题
这个哥们也遇到一样的问题 CUDA 9.1/9.2 与 Visual Studio 2017 (VS2017 15.6.4) 的不兼容问题 错误有显示 #if _MSC_VER < 1600 | ...
- content-disposition attachment filename 在Firefox和IE中得到不同的结果
在Firefox中需要把filename 用双引号包起来,才能得到想要的名字,不然如果含有空格,会丢掉空格后面的部分.而IE会把空格转为_,因此也需要HttpUtility.UrlPathEncode ...