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 ...
随机推荐
- AngularJS学习笔记(四) 自定义指令
指令(directive)是啥?简单来说就是实现一定功能的XXX...之前一直用的ng-model,ng-click等等都是指令.当我有一个ng没提供的需求的时候,就可以自定义个指令.指令的好处显而易 ...
- 【遍历二叉树】09判断二叉树是否关于自己镜像对称【Symmetric Tree】
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 给定一个二叉树,判断是否他自己的镜 ...
- Gym - 101196G :That's One Hanoi-ed Teacher (递推)
题意:给定当前汉诺塔的状态,问还有多少步走完,不合法输出“No”. 思路:显然可以一层一层试探下去的.我们设三个柱子为“起始”,“中转”,“终点”,当前状态的最大的盘子不可能在中转站处:如果在起始站, ...
- javascript获取窗口位置、绝对位置、事件位置等
有段时间没更新博客了,工作实在太忙了,加班加班再加班就是我们这个行业的常态吧...还好最近把工作进度完成了,终于有些空余时间了.关于<Javascript高级程序设计>系列,我并没有弃坑, ...
- ACM学习历程—HDU5585 Numbers(数论 || 大数)(BestCoder Round #64 (div.2) 1001)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5585 题目大意就是求大数是否能被2,3,5整除. 我直接上了Java大数,不过可以对末尾来判断2和5, ...
- ACM学习历程—UESTC 1219 Ba Gua Zhen(dfs && 独立回路 && xor高斯消元)
题目链接:http://acm.uestc.edu.cn/#/problem/show/1219 题目大意是给了一张图,然后要求一个点通过路径回到这个点,使得xor和最大. 这是CCPC南阳站的一道题 ...
- 使用MDI窗体实现多窗口效果
本文章已收录于: C#MDI窗体实现多窗口效果 Visual C#是微软公司推出的下一代主流程序开发语言,他也是一种功能十分强大的程 序设计语言,正在受到越来越多的编程人员的喜欢.在Visua ...
- libvirt, libvirt-python, libvirtd 关系浅析
libvirt 官方解释: http://libvirt.org/ 见分隔线以下. 我的理解:libvirt 作为一个中间层,封装了对下层虚拟化 hypervisor 的操作方法.也就是说,无论你是 ...
- Spring boot 学习一:认识Spring boot
什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员 ...
- @JsonProperty 注解
是Jackson注解.fastjson有可以用. 作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名,比如在很多场景下Java对象的属性是按照规范的驼峰书 ...