es6 Generator函数

声明Generator函数

Generator函数,又叫做生成器函数

	//声明一个demo的Generator函数
	function* demo(value){
		yield `this is ${value}`;
		yield `这是一个demo`;
	}

看起来和普通函数没什么两样,但是他们有两个重要的区别:

  • 普通函数用 function 来声明,Generator函数用 function*声明
  • Generator函数内部有新的关键字:yield,普通函数没有

只是简单的看这个函数可能好多人都会有疑问:这个Generator函数执行后会发生什么??这个关键字yield语句有啥用??

–>那我们来试试吧

调用Generator函数

	//声明一个demo的Generator函数
	function* demo(val){
		yield `this is ${val}`;
		yield `这是一个demo`;
	}

	//调用demo函数
	let demo = demo('小例子');
	// [object Generator]
	demo.next();
	//{value: "this is 小例子", done: false}
	demo.next();
	//{value: "这是一个demo", done: false}
	demo.next();
	//{value: undefined, done: true}
	demo.next();
	//{value: undefined, done: true}

调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是遍历器对象(Iterator Object)

下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。
简单来说
Generator 函数分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行

一开始,我们调用demo(‘小例子’),函数执行后返回一个 [object Generator]生成器对象,我们把它赋值到变量demo中,仅此而已。
然后第一次调用生成器对象demo的next()方法,返回一个对象,done属性的值false,表示遍历还没有结束。
第二次…、
第三次…同样也是返回一个对象,如果没有return语句,则value属性的值为undefined,但是done属性的值true,表示遍历已经结束.
第四次调用,此时 Generator 函数已经运行完毕,next方法返回对象的value属性为undefined,done属性为true。以后再调用next方法,返回的都是这个值。

细心的同学会发现这里生成器的next()方法和遍历器iterator的next()方法返回的结果是不是一样。

本本拿出来记笔记了
调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。

注意:ES6 没有规定,function关键字与函数名之间的星号,写在哪个位置。所以这几种写法都可以,但是推荐使用第三种

	function * fn(v){...}
	function *fn(v){...}
	function* fn(v){...} //推荐使用这种写法
	function*fn(v){...}

yield 表达式

由于Generator函数返回的遍历器对象,只有调用next()方法才会遍历下一个内部状态,yield表达式就是暂停标志。

遍历器对象的next运行逻辑:

  • 遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的表达式的值,作为返回的对象的value属性值。
  • 下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
  • 如果没有遇到新的yield表达式,就一直运行到函数结束,直到遇到return语句为止,将return语句后面的表达式的值,作为返回的对象的value的属性值。
  • 如果该函数没有return语句,则返回的对象的value值为undefined

next()

yield表达式本身没有返回值,或者说总是返回undefinednext方法可以带一个参数该参数就会被当作上一个yield表达式的返回值

	//声明一个demo的Generator的函数
	function* demo(){
		let res = yield `这是一个demo`;
		yield res;
	}

	let iterator = demo();

	iterator.next(); // {value: "这是一个demo", done: false}

	iterator.next('111'); // {value: "111", done: false}

函数体内的第一个yield关键字,把它的返回值赋值给了一个变量res
第一次调用next(),返回对象 {value: “这是一个demo”, done: false},暂停执行
第二次调用next(),传入参数,这时第二个yield关键字紧跟着的是变量res,而变量res的值正是上一个关键字yield的返回值,也就是说这个值正是传入的参数。

next()的参数会作为上一个yield的返回值

next()、throw()、return()

都知道next()是让Generator 函数恢复执行的,但throw()return()同样也可以让Generator 函数恢复执行

简单了解一下

  • next()是将yield表达式替换成一个
  • throw()是将yield表达式替换成一个throw语句
  • return()是将yield表达式替换成一个return语句

yield*表达式

在一个Generator函数里面,如果我们想调用另一个Generator函数,就需要用到的yield*

话不多说直接上代码

	//声明Generator函数: gen1
	function* gen1(){
		yield "a1";
		yield "a2";
	}

	//声明Generator函数: gen2
	function* gen2(){
		yield "b1";
		yield "b2";
	}
	
	//声明Generator函数: gen
	function* gen(){
		yield "start";
		yield* gen1();
		yield* gen2();
		yield "end";
	}

	let ite = gen();

	ite.next(); // {value:"start",done:false}
	ite.next(); // {value:"a1",done:false}
	ite.next(); // {value:"a2",done:false}
	ite.next(); // {value:"b1",done:false}
	ite.next(); // {value:"b2",done:false}
	ite.next(); // {value:"end",done:false}
	

看完例子我们会知道:

这里用了关键字yield*来实现调用另外两个Generator函数

如果一个Generator函数gen执行过程中,进入(调用)了另一个Generator函数gen1/gen2,那么会一直等到Generator函数gen1/gen2全部执行完毕后,才会返回Generator函数gen继续执行。


应用场景

Generator 可以暂停函数执行,可以将异步操作的语句写到yield后面,通过执行next方法进行回调。

  • 异步操作的同步化表达

    Generator函数的暂停执行的效果,意味着可以把异步操作写在yield表达式里面,等到调用next方法时再往后执行。
    这实际上等同于不需要写回调函数了,因为异步操作的后续操作可以放在yield表达式下面,反正要等到调用next方法时再执行。
    所以,Generator函数的一个重要实际意义就是用来处理异步操作,改写回调函数

  • 控制流管理

    回调地狱的解决方案之一

  • 部署 Iterator 接口

    利用 Generator 函数,可以在任意对象上部署 Iterator 接口

  • 作为数据结构

    Generator 可以看作是数据结构,更确切地说,可以看作是一个数组结构,因为 Generator 函数可以返回一系列的值,这意味着它可以对任意表达式,提供类似数组的接口。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值